Pages:
Author

Topic: Working Through the new MtGox Key & Secret API Authentication Model using C# (Read 5035 times)

newbie
Activity: 28
Merit: 0
Oh and the great part if I accidentally posted the apiKey and apiSecret is I could go to MtGox and delete the old and create a new without ever worrying.
newbie
Activity: 1
Merit: 0
       THe following Code is not working , Pls help what I have missed out here, Always getting following msg

"error":"You cannot login to the API with just a login and password".


       Dim ApiKey = "TTTTTTTTTTTT"
       Dim ApiSecretKey ="9o1AuLHkNP5fx8lxfPpzmWtjwjuwUlHL3qVfInTmjYrFjQ=="
       Dim url = "https://mtgox.com/code/cancelOrder.php"       
       Dim params
       
        UserName = "raj"
        Password = "raj"
        Dim orderID = "1111011"
        Dim ordertype = "clos"

        Dim strUrl = url

        Dim req As Net.HttpWebRequest = System.Net.HttpWebRequest.Create(strUrl)

        req.UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)"

        req.Accept = " Application / json"

     
            req.Headers.Add("key", ApiKey)
            params.Add(Tuple.Create("nonce", DateTime.Now.Ticks.ToString()))
            params.add(tuple.Create("name", UserName))
            params.add(tuple.Create("pass", Password))
            params.add(tuple.Create("orderID", orderID))
            params.add(tuple.Create("orderType", ordertype))



        If params.Count Then
            req.AllowWriteStreamBuffering = True
            req.Method = "POST"
            req.ContentType = "application/x-www-form-urlencoded"
           
Dim postSB As New System.Text.StringBuilder()

For Each param In params
                If postSB.Length Then postSB.Append("&")
                postSB.Append(param.Item1)
                postSB.Append("=")
                postSB.Append(param.Item2)
Next

Dim postBin = System.Text.Encoding.ASCII.GetBytes(postSB.ToString())


 If authRequired Then
                Dim hmac = System.Security.Cryptography.HMACSHA512.Create()
                hmac.Key = Convert.FromBase64String(ApiSecretKey)
                Dim hash = hmac.ComputeHash(postBin)
                req.Headers.Add("secret", Convert.ToBase64String(hash))
 End If

 req.GetRequestStream.Write(postBin, 0, postBin.Length)

 End If



Dim response = req.GetResponse.GetResponseStream()
   
Dim reader As IO.StreamReader = New IO.StreamReader(response)
   
MsgBox(reader.ReadToEnd)

End Sub
hex
newbie
Activity: 45
Merit: 0
newbie
Activity: 3
Merit: 0
I have tried removing them but it just throws the must be logged in error  Huh
hex
newbie
Activity: 45
Merit: 0
Try removing username and password from code ?
newbie
Activity: 3
Merit: 0
been a while since anyone posted on here..
Hex i was just wandering if your vb code still works, as i tried it the other day with valid credentials and got this error message:
"You cannot login to the API with just a login and password", and yes i used my api key/secret key.
hex
newbie
Activity: 45
Merit: 0
nope, it does not work without key and signature.
I gave granted get_info and trade rights to my key.
newbie
Activity: 29
Merit: 0
I thought I'd hear something back by now but I haven't.

In any case, the only thing I can suggest is remove the Api Key and Secret from the header and see if your application still works. If it does, it means that your key/secret isn't actually being used and the un&pw is getting precedence.

I looked at your code, it looks good to me. So the only next thing I can think that is requiring un/pw is you haven't gone to your mtgox api page and set the necessary rights for that key. Check all to on. If you don't know what I mean, you can check out the videos on www.automtgox.com. There's a part in the 2nd video that shows how to set api keys.

Anyway, once the rights are assigned, you shouldn't need to pass the un/pw.
hex
newbie
Activity: 45
Merit: 0
I understand you compleatly.

I will chenge api as soon as un and pw are no longer required.
newbie
Activity: 29
Merit: 0
I notified mark and I've updated the wiki's api for discussion.

There is nothing fundamentally wrong with using the username and password strategy, but it does compromise the security of the user's private account and defeats the ENTIRE purpose of the api key/secret rights.

I mean, if its a personal application, it doesn't hurt anything, but if it's an application like www.automtgox.com, a service; there's a piece of mind I want to provide my customers. I shouldn't have  their passwords on other services.


I know why this happened too. It is because the old password implementation is still functional and coders are having a lot of trouble getting the key/secret model working and there are a hundred articles still out there describing how to use the old api with username and password.

But to prove I'm not crazy, this is the information on MtGox about key/secret. The wiki used to reflect the same information, and now it doesn't... Note that it does not mention user name or password.

https://mtgox.com/support/tradeAPI
hex
newbie
Activity: 45
Merit: 0

Please do check with them and inform me.
newbie
Activity: 29
Merit: 0
The implementation I gave works and doesn't require username or password.

The whole point of an api key/secret implementation is to give user control of their account so they can revoke rights to an application. If they give up their username and password to applications, they can't guarantee that the application owner won't hijack the account. User should NEVER give out user name and passwords.  That's the whole point.

Anyway, I'll let them know over at MtGox that someone has compromised the wiki. Or maybe something changed recently that I don't know about.



hex
newbie
Activity: 45
Merit: 0
No it requires BOTH.
Just like it says in documentation: https://en.bitcoin.it/wiki/MtGox/API
"In addition to the "nonce" value, your POST data must also include your username and password values, named "name" and "pass" respectively."

I tried removing them but it does not works.




newbie
Activity: 29
Merit: 0
hex, I am confused by your implementation. I see you include in your request username and password. Does your model allow for either username/password or key/secret to be passed?
hex
newbie
Activity: 45
Merit: 0
Here is mine vb.net class. You just supply it credentials and it returns parsed json Smiley

Code:
' bitcointalk.org - hex, GPL
Public Class MtGoxAPI
Public Property ApiKey As String
Public Property ApiSecretKey As String
Public Property UserName As String
Public Property Password As String

Public Enum Urls
GetTicker
GetDepth
GetTrades
GetFunds
BuyBTC
SellBTC
GetOrders
Info
'...
End Enum

Private Function GetUrl(url As Urls) As String
Select Case url
Case Urls.GetTicker
Return "http://mtgox.com/api/0/data/ticker.php"
Case Urls.GetDepth
Return "http://mtgox.com/api/0/data/getDepth.php"
Case Urls.GetTrades
Return "http://mtgox.com/api/0/data/getTrades.php"
Case Urls.GetFunds
Return "https://mtgox.com/api/0/getFunds.php"
Case Urls.BuyBTC
Return "https://mtgox.com/api/0/buyBTC.php"
Case Urls.SellBTC
Return "https://mtgox.com/api/0/sellBTC.php"
Case Urls.GetOrders
Return "https://mtgox.com/api/0/getOrders.php"
Case Urls.Info
Return "https://mtgox.com/api/0/info.php"
Case Else
Throw New NotImplementedException()
End Select
End Function

Public Shared Function UrlEncode(url As String) As String
Dim r = url.Replace("!", "%21")
r = r.Replace("*", "%2A")
r = r.Replace("'", "%27")
r = r.Replace("(", "%28")
r = r.Replace(")", "%29")
r = r.Replace(";", "%3B")
r = r.Replace(":", "%3A")
r = r.Replace("@", "%40")
r = r.Replace("&", "%26")
r = r.Replace("=", "%3D")
r = r.Replace("+", "%2B")
r = r.Replace("$", "%24")
r = r.Replace(",", "%2C")
r = r.Replace("/", "%2F")
r = r.Replace("?", "%3F")
r = r.Replace("#", "%23")
r = r.Replace("[", "%5B")
r = r.Replace("]", "%5D")
Return r
End Function

Public Function Request(url As Urls, params As List(Of Tuple(Of String, String))) As Newtonsoft.Json.Linq.JObject

Dim strUrl = GetUrl(url)
If params Is Nothing Then params = New List(Of Tuple(Of String, String))

Dim req As Net.HttpWebRequest = System.Net.HttpWebRequest.Create(strUrl)
req.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:8.0) Gecko/20110920 Firefox/8.0"

Dim authRequired = Not (url = Urls.GetTicker Or url = Urls.GetDepth Or url = Urls.GetTrades)

If authRequired Then
If String.IsNullOrEmpty(ApiKey) Or String.IsNullOrEmpty(ApiSecretKey) Or _
String.IsNullOrEmpty(UserName) Or String.IsNullOrEmpty(Password) Then Throw New ArgumentNullException("auth properties not set")

req.Headers.Add("Rest-Key", ApiKey)
params.Add(Tuple.Create("nonce", DateTime.Now.Ticks.ToString()))
params.Add(Tuple.Create("name", UserName))
params.Add(Tuple.Create("pass", Password))
End If

If params.Count Then
' we need to POST
req.AllowWriteStreamBuffering = True
req.Method = "POST"
req.ContentType = "application/x-www-form-urlencoded"
Dim postSB As New System.Text.StringBuilder()
For Each param In params
If postSB.Length Then postSB.Append("&")
postSB.Append(UrlEncode(param.Item1))
postSB.Append("=")
postSB.Append(UrlEncode(param.Item2))
Next
Dim postBin = System.Text.Encoding.ASCII.GetBytes(postSB.ToString())

If authRequired Then
Dim hmac = System.Security.Cryptography.HMACSHA512.Create()
hmac.Key = Convert.FromBase64String(ApiSecretKey)
Dim hash = hmac.ComputeHash(postBin)
req.Headers.Add("Rest-Sign", Convert.ToBase64String(hash))
End If

req.GetRequestStream.Write(postBin, 0, postBin.Length)
End If



Dim response = req.GetResponse.GetResponseStream()
Dim reader As IO.StreamReader = New IO.StreamReader(response)
'Return reader.ReadToEnd()

Return Newtonsoft.Json.Linq.JObject.Parse(reader.ReadToEnd())

End Function



End Class
newbie
Activity: 29
Merit: 0
Could you link your other post to this post so others may benefit? I still can't reply on that thread. I wish a moderator would set me up.
legendary
Activity: 1304
Merit: 1015
Thank you.  I got it working without the username and password.  Awesome.  PM me about your service.
newbie
Activity: 29
Merit: 0
Oh and the great part if I accidentally posted the apiKey and apiSecret is I could go to MtGox and delete the old and create a new without ever worrying.
newbie
Activity: 29
Merit: 0
Sorry about that. That's what I get for posting in the wee hours of the morning. That part is pretty much the same as yours.

Code:
protected string EncodeParamsToSecret( string parameters ) {
var hmacsha512 = new HMACSHA512( Convert.FromBase64String( this.apiSecret ) );
var byteArray = hmacsha512.ComputeHash( Encoding.UTF8.GetBytes( parameters ) );
return Convert.ToBase64String( byteArray );
}


I'll give you more of the code so you can see how the api you're calling would work... I'm using
Newtonsoft Json for my json parser.

Code:
protected JObject JsonPost( string moreargs = null ) {
return JsonConvert.DeserializeObject( Post( moreargs ) );
}

public const string PRIVATE_URL = "https://mtgox.com/api/0/";

public JObject SendBTC( string walletaddress, double amt ) {
Url = new Uri( PRIVATE_URL + "withdraw.php" );
return jObj = JsonPost( string.Format( "group1=BTC&btca={0}&amount={1:f6}", walletaddress, amt ) );
}


Let me know if there's any other pieces I've left out. Obviously you'll have to wrap the function in a class, and set member strings apiKey and apiSecret as you require as well.

Good luck.

Maybe when I get my revised service back online, you'll blog about it.
legendary
Activity: 1304
Merit: 1015
Thanks for that!  Grin  I'll have to take a look at it tonight after work.  I noticed there was a method in there "EncodeParamsToSecret( parameters );" that was not in the code you posted.  You don't mind posting that method do you (without the key and secret of course.)
Pages:
Jump to: