How Should I compute signatures in API? - vb.net

I want to create API for yobit. For now, I will do something very simple, namely get info.
In Python, the code sort of looks like this
url = 'https://yobit.net/tapi'
values['method'] = method
values['nonce'] = str(int(time.time()))
body = urlencode(values)
signature = hmac.new(self.secret, body, hashlib.sha512).hexdigest()
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Key': self.key,
'Sign': signature
}
I basically want to replace code hmac.new(self.secret, body, hashlib.sha512).hexdigest() with vb.net equivalent.
This my current code
Public Overrides Sub readbalances()
Dim secret = _secret
Dim url = "https://yobit.net/tapi"
Dim key = New Tuple(Of String, String)("Key", _apiKey)
Dim parameters = "method=getInfo&nonce=" + Str(Int(DateTime.Now))
Dim sig = New System.Security.Cryptography.HMACSHA512().ToString 'What should I put here?
Dim sigtupple = New Tuple(Of String, String)("Sign", sig)
Dim result = CookieAwareWebClient.downloadString1("url", {key, sigtupple}, parameters)
End Sub
What should I do?
Content of downloadString1 is the following but let's just say it performs as expected
Public Shared Function downloadString1(url As String, headers As Tuple(Of String, String)(), postdata As String) As String
Dim wc = New CookieAwareWebClient
For Each header In headers
wc.Headers.Add(header.Item1, header.Item2)
Next
Dim result = wc.UploadString(url, postdata)
Return result
End Function

Related

How to translate this javascript code to vb.net

It's a simple code
var contentHash = CryptoJS.SHA512(JSON.stringify(requestBody)).toString(CryptoJS.enc.Hex);
Also it's actually simpler. I think requestBody is just an empty string.
https://bittrex.github.io/api/v3#topic-Authentication
What I tried is to do
Dim hasher = New System.Security.Cryptography.HMACSHA512(System.Text.Encoding.UTF8.GetBytes(""))
Dim contentHash = ExchangesClass.getString(hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes("")))
Where ExchangeClass.getString is
Public Shared Function getString(sigs As Byte()) As String
Dim list = New Generic.List(Of String)
For Each b In sigs
Dim chunk = b.ToString("x2")
list.Add(chunk)
Next
Dim result = String.Concat(list)
Dim result2 = BitConverter.ToString(sigs).Replace("-", "").ToLower()
Debug.Assert(result = result2)
Return result
End Function
But that's sort of weird. Why would anyone want a hash of an empty string. Unless I am missing something. I do not see where requestBody is. Perhaps because I use only read only API of bittrex
This code works
So
var contentHash = CryptoJS.SHA512(JSON.stringify(requestBody)).toString(CryptoJS.enc.Hex);
becomes
Protected Overridable Function computeSigNoHmac(content As String) As String
Dim hasher2 = New System.Security.Cryptography.SHA512Managed() 'create hashers based on those bytes
Dim hashbytes = hasher2.ComputeHash(System.Text.Encoding.UTF8.GetBytes(content)) 'compute the hash and get bytes
Dim sighash2 = BitConverter.ToString(hashbytes).Replace("-", "").ToLower() 'turn bytes into hex string (0-9a-f)
Return sighash2
End Function
Also, for completion,
var signature = CryptoJS.HmacSHA512(preSign, apiSecret).toString(CryptoJS.enc.Hex);
Becomes
Protected Overridable Function computeSig(content As String, secret As String) As String
Dim secretinBytes = System.Text.Encoding.UTF8.GetBytes(secret) 'Turn secret hex into bytes (0-9a-f)
Dim hasher2 = New System.Security.Cryptography.HMACSHA512(secretinBytes) 'create hashers based on those bytes
'Dim hasher3 = New System.Security.Cryptography.SHA512(secretinBytes) 'create hashers based on those bytes
Dim hashbytes = hasher2.ComputeHash(System.Text.Encoding.UTF8.GetBytes(content)) 'compute the hash and get bytes
Dim sighash2 = BitConverter.ToString(hashbytes).Replace("-", "").ToLower() 'turn bytes into hex string (0-9a-f)
Return sighash2
End Function

YoBit tapi problems with authetincation

I am trying to write simple application for myself and when i try to call
getInfo method i always get a error into the response. Key, sign, method or nonce is incorrect. I found a number of examples but i still can't find mistake in my code. Could anyone help me with it?
The code works fine for hitbtc. I know yobit is a bit different but I think I have accomodate that.
My code:
Protected Shared Function readStrings(signatureheader As String, host As String, pathandQuery As String, post As String, secret As String, hasher As System.Security.Cryptography.HMAC, otherHeaders As Tuple(Of String, String)()) As String
'apikey=98998BEEB8796455044F02E4864984F4
'secret=44b7659167ffc38bb34fa35b5c816cf5
hasher.Key = exchanges.getBytes(secret)
Dim url = host + pathandQuery ' url = "https://yobit.net/tapi/"
Dim wc = New CookieAwareWebClient()
Dim sigHash2 = ""
If post = "" Then
sigHash2 = CalculateSignature2(pathandQuery, hasher)
Else
'post = "method=getInfo&nonce=636431012620"
sigHash2 = CalculateSignature2(post, hasher) 'sighash2= "ece0a3c4af0c68dedb1f840d0aef0fd5fb9fc5e808105c4e6590aa39f4643679af5da52b97d595cd2277642eb27b8a357793082007abe1a3bab8de8df24f80d2"
End If
wc.Headers.Add(signatureheader, sigHash2) ' SignatureHeader ="Sign"
Dim response = ""
For Each oh In otherHeaders ' otherHeaders =(0) {(Key, 98998BEEB8796455044F02E4864984F4)} System.Tuple(Of String, String)
wc.Headers.Add(oh.Item1, oh.Item2)
Next
'- wc.Headers {Sign: ece0a3c4af0c68dedb1f840d0aef0fd5fb9fc5e808105c4e6590aa39f4643679af5da52b97d595cd2277642eb27b8a357793082007abe1a3bab8de8df24f80d2 Key: 98998BEEB8796455044F02E4864984F4 } System.Net.WebHeaderCollection
'url = "https://yobit.net/tapi/"
'post = "method=getInfo&nonce=636431012620"
If post = "" Then
response = wc.DownloadString(url)
Else
response = wc.UploadString(url, post) 'response = response "{"success":0,"error":"invalid key, sign, method or nonce"}" String
End If
Return response
End Function
The code has been tested succesfully for hitbtc.
So the crypto part is correct. I put it here anyway for completeness
Protected Shared Function CalculateSignature2(text As String, hasher As System.Security.Cryptography.HMAC) As String
Dim siginhash = hasher.ComputeHash(exchanges.getBytes(text))
Dim sighash = exchanges.getString(siginhash)
Return sighash
End Function
So,
for sanity check
This code works
Public Overrides Sub readbalances()
Dim response = readStrings("X-Signature", "https://api.hitbtc.com", "/api/1/trading/balance?nonce=" + exchanges.getNonce().ToString + "&apikey=" + _apiKey, "", _secret, New System.Security.Cryptography.HMACSHA512(), {})
End Sub
With yobit things are different. I got to use post instead of get. I got to add more headers. However, I think I have fixed that.
It doesn't work.
The python function for yobit API is this I just need to translate that to vb.net which I think I have done faithfully
API Call Authentication in Python ( Working PHP example )
I think the mistake is around here
request_url = "https://yobit.net/tapi";
request_body = "method=TradeHistory&pair=ltc_btc&nonce=123";
signature = hmac_sha512(request_body,yobit_secret);
http_headers = {
"Content-Type":"application/x-www-form-urlencoded",
"Key":yobit_public_key,
"Sign":signature
}
response = http_post_request(request_url,request_body,http_headers);
result = json_decode(response.text);
There the stuff that I copied is method=getInfo&nonce=636431012620 which is what I put in post.
So that seems right.
Looks like it works.
I just need to change the nonce so that it's between 0 to 2^31
So this is the error
post = "method=getInfo&nonce=636431012620
The nonce shouldn't be that big. At most it should be
2147483646
Also though not documented, I must add
content type as one of the header. This is the final solution
Dim nonce = exchanges.getNonce().ToString
Dim content = hashObject("", nonce, "method=getInfo&nonce=")
Dim sighash = computeSig(content)
Dim result = CookieAwareWebClient.downloadString1("https://yobit.net/tapi/", content, {New Tuple(Of String, String)("Key", _apiKey), New Tuple(Of String, String)("Sign", sighash), New Tuple(Of String, String)("Content-Type", "application/x-www-form-urlencoded")})
So I added New Tuple(Of String, String)("Content-Type", "application/x-www-form-urlencoded") as one of the headers
Protected Overridable Function computeSig(content As String) As String
Dim hasher = New System.Security.Cryptography.HMACSHA512(System.Text.Encoding.UTF8.GetBytes(_secret))
Return CalculateSignature2(content, hasher)
End Function
Public Shared Function CalculateSignature2(content As String, hasher As System.Security.Cryptography.HMAC) As String
Dim siginhash = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(content))
Dim sighash = exchanges.getString(siginhash) 'convert bytes to string
Return sighash
End Function
Public Shared Function downloadString1(url As String, post As String, otherHeaders As Tuple(Of String, String)()) As String
Dim wc = New CookieAwareWebClient()
For Each oh In otherHeaders
wc.Headers.Add(oh.Item1, oh.Item2)
Next
Dim response = String.Empty
Try
If post = "" Then
response = wc.DownloadString(url)
Else
response = wc.UploadString(url, post)
End If
Catch ex As Exception
Dim a = 1
End Try
Return response
End Function

VB.NET How to parse and add the result into the list(of string) from json file?

I'm creating a launcher for Minecraft. I have a problem, My launcher using json files to load and check files. How can I add the strings from this json (example) into the AssetsList? https://s3.amazonaws.com/Minecraft.Download/indexes/1.8.json
My code, if it helps you to understand me (I'm using Newtonsoft.json to parse json):
The MCAssets class:
Public Class MCAssets
Public hash As String
End Class
The list:
Public AssetsList As New List(Of String)
The funchtion to get the assets:
Public Async Function GetAssets() As Task
If Not Directory.Exists(Root + "\assets\indexes") Then
Directory.CreateDirectory(Root + "\assets\indexes")
End If
Dim client = New WebClient()
Await client.DownloadFileTaskAsync(New Uri(String.Format("http://s3.amazonaws.com/Minecraft.Download/indexes/{0}.json", AssetIndex)), String.Format(Root + "\assets\indexes\{0}.json", AssetIndex))
Dim reader As New StreamReader(Root + "\assets\indexes\" + AssetIndex + ".json")
Dim assets As String = reader.ReadToEnd()
reader.Close()
Dim jsonresult = JsonConvert.DeserializeObject(Of Object)(assets)
For Each i In jsonresult("objects").Children()
AssetsList.Add(i.ToObject(Of MCAssets).hash)
Next
End Function
If you want know more about Minecraft assets, visit this: https://github.com/tomsik68/mclauncher-api/wiki/Minecraft-1.6-resources
You can do something like this:
Dim assetsObject = JsonConvert.DeserializeObject(Of JObject)(assets) 'assets is your json file
Dim allAssets = (From i In assetsObject("objects").Children() _
Select New MCAssets() With {.hash = i.First.Value(Of String)("hash")}).ToList()
By the way, there is not really a need to make a custom class. You can just add all of the hashes to a list of string like so:
Dim assetsObject = JsonConvert.DeserializeObject(Of JObject)(assets)
Dim allAssets = (From i In assetsObject("objects").Children() _
Select i.First.Value(Of String)("hash"))

Use generic type to create new instance of that objects

I am very new to Generics and it looks promising towards my problem although I have some questions around it.
I am in the process to build a generic function that will deserialize xml into an object and then create an ArrayList of that object and return it.
My question is how will I go to implement generics to do so? To be more clear I need to create new instance of object and assign values to its properties.
This is my function:
Private Function DeSerializeArrayList(serializedData As String, ByVal ObjectName As Object, ByVal ObjType As System.Type, ByVal ReturnObjectType As System.Type) As ArrayList
Dim list As New ArrayList()
Dim extraTypes As Type() = New Type(0) {}
extraTypes(0) = ObjectName.GetType()
'Code fails here and says can't include anonymous class
Dim serializer As New System.Xml.Serialization.XmlSerializer(ObjectName.GetType(), extraTypes)
Dim xReader As XmlReader = XmlReader.Create(New StringReader(serializedData))
Try
Dim obj = serializer.Deserialize(xReader)
For i As Integer = 0 To obj.Items.Length - 1
'Need to create NEW object
Dim labPrice As Type() = New Type(0) {}
labPrice(0) = ReturnObjectType
'Need some method to get the properties of that object
'Dim s = labPrice(0).GetEnumNames
'Need to asign values to that object's properties
'With labPrice
' .fLabPricelistID = obj.Items(i).fLabPricelistID
' .ftariffCode = obj.Items(i).fTariffCode
' .fSurfaced = obj.Items(i).fSurfaced
' .fLabCostPrice = obj.Items(i).fLabCostPrice
' .fLabDiscountedPrice = obj.Items(i).fLabDiscountedPrice
' .fEffectiveDate = obj.Items(i).fEffectiveDate
' .fLaboratoryCodeID = obj.Items(i).fLaboratoryCodeID
' .fDescription = obj.Items(i).fDescription
' .flabProduct = obj.Items(i).fLabProduct
' .fActive = obj.Items(i).fActive
'End With
'list.Add(labPrice)
Next
Catch
Throw
Finally
xReader.Close()
End Try
Return list
End Function
I found a solution that works perfectly for my problem that I had:
Dim obj = DeserializeObject(Of TestObject)(xmlString)
'Function will map xml to object/list of objects
Public Function DeserializeObject(Of T)(xml As String) As T
Dim xs As New XmlSerializer(GetType(T))
Dim memoryStream As New MemoryStream(StringToUTF8ByteArray(xml))
Dim xmlTextWriter As New XmlTextWriter(memoryStream, Encoding.UTF8)
Dim obj = DirectCast(xs.Deserialize(memoryStream), T)
Return obj
End Function
Public Shared Function StringToUTF8ByteArray(stringVal As String) As [Byte]()
Dim encoding As New UTF8Encoding()
Dim byteArray As Byte() = encoding.GetBytes(stringVal)
Return byteArray
End Function

Split string after the = sign

I can't seem to work out how to get a value from my string using VB.net
If I have a string in my textbox that says:
WWW-Authenticate: Digest realm="MyServer",qop="auth",algorithm="MD5",maxbuf=1000,nonce="3b010c090c0a0000c0a80157c7007f03c5",opaque="4e6573732041636365737320436f6e74"
How can I get each of the values after the = in the string.
I have tried using
Dim s = "WWW-Authenticate: Digest realm='MyServer',qop='auth',algorithm='MD5',maxbuf=1000,nonce='3b010c090c0a0000c0a80157c7007f03c5',opaque='4e6573732041636365737320436f6e74'"
Dim pattern = "="
Dim matches = Regex.Matches(s, pattern)
Dim values = matches.OfType(Of Match).Select(Function(m) m.Value)
For Each v In values
MsgBox(v)
Next
But it only returns the = in the messagebox.
I want to be able to get just the part after the = sign.
Anyone able to help?
I have tried using the following but it still includes the realm= qop= etc.. in the string. (but includes it at the end of the next item.
Dim s = "WWW-Authenticate: Digest realm='Ness Access Control',qop='auth',algorithm='MD5',maxbuf=1000,nonce='3b010c090c0a0000c0a80157c7007f03c5',opaque='4e6573732041636365737320436f6e74'"
Dim result_array As Array = Split(s, "=", 6)
For Each v In result_array
MsgBox(v)
Next
Regular Expressions!
Imports System.Text.RegularExpressions
Module Module1
Sub Main()
Dim s As String = "WWW-Authenticate: Digest realm='MyServer',qop='auth',algorithm='MD5',maxbuf=1000,nonce='3b010c090c0a0000c0a80157c7007f03c5',opaque='4e6573732041636365737320436f6e74'"
'Regular Expression, matches word before equals, and word after equals
Dim r As New Regex("(\w+)\='([^']+)'")
'All the matches!
Dim matches As MatchCollection = r.Matches(s)
For Each m As Match In matches
'm.Groups(1) = realm, qop, algorithm...
'm.Groups(2) = MyServer, auth, MD5...
Console.WriteLine(m.Groups(2))
Next
Console.ReadLine()
End Sub
End Module
And if you want everything in a nice key-value dictionary:
Dim dict As New Dictionary(Of String, String)
For Each m As Match In matches
'm.Groups(1) = realm, qop, algorithm...
'm.Groups(2) = MyServer, auth, MD5...
dict(m.Groups(1).ToString()) = dict(m.Groups(2).ToString())
Next
A case for a specific string extension.
How to transform a specific formatted string in a Dictionary with keys and values
Public Module StringModuleExtensions
<Extension()>
Public Function ToStringDictionary(ByVal str as String, _
ByVal OuterSeparator as Char, _
ByVal NameValueSeparator as Char) _
As Dictionary(of String, String)
Dim dicText = New Dictionary(Of String, String)()
if Not String.IsNullOrEmpty(str) then
Dim arrStrings() = str.TrimEnd(OuterSeparator).Split(OuterSeparator)
For Each s in arrStrings
Dim posSep = s.IndexOf(NameValueSeparator)
Dim name = s.Substring(0, posSep)
Dim value = s.Substring(posSep + 1)
dicText.Add(name, value)
Next
End If
return dicText
End Function
End Module
Call with
Dim test = "WWW-Authenticate: Digest realm=""MyServer"",qop=""auth"",algorithm=""MD5"", maxbuf=1000,nonce=""3b010c090c0a0000c0a80157c7007f03c5"",opaque=""4e6573732041636365737320436f6e74"""
Dim dict = test.ToStringDictionary(","c, "="c)
For Each s in dict.Keys
Console.WriteLine(dict(s))
Next
(probably you need to remove the WWW-Authenticate line before.
You are looking for the split() function.
Dim logArray() As String
logArray = Split(s, "=")
For count = 0 To logArr.Length - 1
MsgBox(logArray(count))
Next