Bitcoin Forum
May 07, 2024, 01:36:18 AM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1] 2 »  All
  Print  
Author Topic: Working Through the new MtGox Key & Secret API Authentication Model using C#  (Read 5032 times)
mdbitcoin (OP)
Newbie
*
Offline Offline

Activity: 29
Merit: 0


View Profile
July 25, 2011, 07:46:12 AM
 #1

I signed in to help jimbobway on another thread but due to new user restrictions I can't answer him there.

http://forum.bitcoin.org/index.php?topic=29843.0


However, this is msg will probably help other C# coders trying to break through the learning curve since the new service can be a pain to authenticate to unless it's absolutely right. I lost the better half of the day to it but others have helped me in the past, so hope it helps...

Keep in mind, you'll have to supply your own Json Parser to the return string of Post

Code:
		protected string Post( string moreargs = null ) {
// Verify client was instantiated with apikey and apisecret
if( string.IsNullOrEmpty( this.apiKey ) || string.IsNullOrEmpty( this.apiSecret ) )
throw new ArgumentException( "Cannot call private api's without api key and secret" );

// Create web request to mtgox

var parameters = "nonce=" + DateTime.Now.Ticks.ToString();
if( !string.IsNullOrEmpty( moreargs ) )
parameters += "&" + moreargs;
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create( Url );

webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Method = "POST";
webRequest.UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)"; // you should probably key this with your client so they can help diagnose issues for you in their logs!!!
webRequest.Accept = "application/json";
// Required to authenticate on MtGox

webRequest.Headers["Rest-Key"] = this.apiKey;
webRequest.Headers["Rest-Sign"] = EncodeParamsToSecret( parameters );

byte[] byteArray = Encoding.UTF8.GetBytes( parameters );
webRequest.ContentLength = byteArray.Length;

using( Stream dataStream = webRequest.GetRequestStream() ) {
dataStream.Write( byteArray, 0, byteArray.Length );
}

using( WebResponse webResponse = webRequest.GetResponse() ) {
using( Stream str = webResponse.GetResponseStream() ) {
using( StreamReader sr = new StreamReader( str ) ) {
return sr.ReadToEnd();
}
}
}
}





1715045778
Hero Member
*
Offline Offline

Posts: 1715045778

View Profile Personal Message (Offline)

Ignore
1715045778
Reply with quote  #2

1715045778
Report to moderator
1715045778
Hero Member
*
Offline Offline

Posts: 1715045778

View Profile Personal Message (Offline)

Ignore
1715045778
Reply with quote  #2

1715045778
Report to moderator
The block chain is the main innovation of Bitcoin. It is the first distributed timestamping system.
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1715045778
Hero Member
*
Offline Offline

Posts: 1715045778

View Profile Personal Message (Offline)

Ignore
1715045778
Reply with quote  #2

1715045778
Report to moderator
1715045778
Hero Member
*
Offline Offline

Posts: 1715045778

View Profile Personal Message (Offline)

Ignore
1715045778
Reply with quote  #2

1715045778
Report to moderator
1715045778
Hero Member
*
Offline Offline

Posts: 1715045778

View Profile Personal Message (Offline)

Ignore
1715045778
Reply with quote  #2

1715045778
Report to moderator
mdbitcoin (OP)
Newbie
*
Offline Offline

Activity: 29
Merit: 0


View Profile
July 25, 2011, 08:28:52 AM
 #2

Be aware, that general misleading error: "{"error":"Must be logged in"}" will apply in every failed case except authorization for rights.

jimbobway
Legendary
*
Offline Offline

Activity: 1304
Merit: 1014



View Profile
July 25, 2011, 01:36:16 PM
 #3

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.)
mdbitcoin (OP)
Newbie
*
Offline Offline

Activity: 29
Merit: 0


View Profile
July 25, 2011, 08:40:19 PM
 #4

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<JObject>( 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.
mdbitcoin (OP)
Newbie
*
Offline Offline

Activity: 29
Merit: 0


View Profile
July 25, 2011, 08:44:25 PM
 #5

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.
jimbobway
Legendary
*
Offline Offline

Activity: 1304
Merit: 1014



View Profile
July 26, 2011, 12:58:59 AM
 #6

Thank you.  I got it working without the username and password.  Awesome.  PM me about your service.
mdbitcoin (OP)
Newbie
*
Offline Offline

Activity: 29
Merit: 0


View Profile
July 26, 2011, 01:25:30 AM
 #7

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.
hex
Newbie
*
Offline Offline

Activity: 45
Merit: 0



View Profile WWW
September 21, 2011, 02:42:00 PM
 #8

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
mdbitcoin (OP)
Newbie
*
Offline Offline

Activity: 29
Merit: 0


View Profile
September 21, 2011, 09:51:03 PM
 #9

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
*
Offline Offline

Activity: 45
Merit: 0



View Profile WWW
September 21, 2011, 10:02:21 PM
 #10

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.




mdbitcoin (OP)
Newbie
*
Offline Offline

Activity: 29
Merit: 0


View Profile
September 21, 2011, 11:41:36 PM
 #11

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
*
Offline Offline

Activity: 45
Merit: 0



View Profile WWW
September 22, 2011, 12:04:12 AM
 #12


Please do check with them and inform me.
mdbitcoin (OP)
Newbie
*
Offline Offline

Activity: 29
Merit: 0


View Profile
September 22, 2011, 12:48:16 AM
 #13

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
*
Offline Offline

Activity: 45
Merit: 0



View Profile WWW
September 22, 2011, 10:03:37 AM
 #14

I understand you compleatly.

I will chenge api as soon as un and pw are no longer required.
mdbitcoin (OP)
Newbie
*
Offline Offline

Activity: 29
Merit: 0


View Profile
September 23, 2011, 12:36:33 AM
 #15

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
*
Offline Offline

Activity: 45
Merit: 0



View Profile WWW
September 23, 2011, 01:30:57 PM
 #16

nope, it does not work without key and signature.
I gave granted get_info and trade rights to my key.
SupremePlus
Newbie
*
Offline Offline

Activity: 3
Merit: 0


View Profile
May 12, 2012, 02:32:53 PM
 #17

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
*
Offline Offline

Activity: 45
Merit: 0



View Profile WWW
May 16, 2012, 11:35:11 AM
 #18

Try removing username and password from code ?
SupremePlus
Newbie
*
Offline Offline

Activity: 3
Merit: 0


View Profile
May 16, 2012, 02:44:23 PM
 #19

I have tried removing them but it just throws the must be logged in error  Huh
hex
Newbie
*
Offline Offline

Activity: 45
Merit: 0



View Profile WWW
May 16, 2012, 11:00:15 PM
 #20

I don't know then :/
Pages: [1] 2 »  All
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!