Bitcoin Forum

Bitcoin => Bitcoin Technical Support => Topic started by: Nefario on May 23, 2011, 07:46:20 AM



Title: Paying to get RSA signing working in Javascript
Post by: Nefario on May 23, 2011, 07:46:20 AM
I hate Javascript, hate it with a passion

The person that solves this will get 70Bitcoins, and can (for another 120Bitcoins) continue on and develope this into an interface for GLBSE. As well as the bitcoin itself there will be major credit for this, and your name will be added to GLBSE's (soon to be created) contributors page.

I am attempting to use some Javascript libraries to sign base64 encoded data with an RSA prvate key, the signature is then also encoded base64 which is sent to a server, the server verifies it with the public key, and then I do some stuff.

The problem is the JavaScript lib's seem to be signing but the output is not correct.


Private key is:
Code:
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA9cbXaYIbd41nTHnMcs4KGtsc+N+k4n/yQUJSoEq2F7Tz742a
ZZZU+DZCQ7T/4ZHkmTtO2tYY877ptdIn7uJwGEbh6uwqEoO4Q9kYbbMyrsFCFozh
Q+Ro0goztGmqcXwn0p1K70Yay/4UbNoZUs86HgsuZyb7pLChzDoAWTp4gzLBxVq9
su9xENuYEd/5viKvwGY7EaKtWqLj4GaM7YPhINwWC+nGI+EobmeTKTxWcFj+/azw
1pv8iXNZ53mc6kVWCCNoEpqrVtV7OJ2rEQoVzfhmcA0ODMqGIg9SpsOOJLcN/8WB
B8Oj/cSQuvKotrkUw+4FEHxbv6NULqm102/hcwIDAQABAoIBAB4dNPuqg28MlmGa
cuCGOlq8Cjq8PFm8T5SLadBWFyWkeFcbxJU57ENVcp0VKl0bISVdTPYnUXtcIwqy
K05r1ExFMx0zvpvyI7u8d+/JCya6azyUGm3VKLrDoT4zzDyHd+GogCv9LP9drGcB
+iRZW8eemxrsfdzZ/5kkajKEpYt9iSRmsem2u5ylQb8eA4sfsi1lqU/3OUhf7NpG
tq4UFZMCtNmDMdsH97049aqO5PswIY4odN35qHYjn9r4FdSHHY0Cy6qU84dY6Y3z
40erWs4/0yFNSrloc6rXOCiuIz9L9pOVy/ovKWz3T9+lq7/sEBo4tzixI+uNQ00m
nzDyjRECgYEA+371ZGI4tSqd77ZbG+GQHJxm8P2TkGSZMeU0jieqAfyLSJkAxuXb
lTWXNCkmpkbzHHUzFMkjNhg8qYfOETdHnebmypgL/1V+lYxbAhgN/guP0a7GHo1v
fXSk2k+F6/sI4JGi072JF3y0jSBIH64Zy1rotksBuBqFI+onYxfZnWcCgYEA+i2p
b321Wk0fjM0FYzaQPOaqFQqKpFaY3PMcioLxByYXjLl99m+iJbTe0QUq72juoNmk
rJnK8vQs/1rDLO5ShMxcJ7tyOyOQosKYMBiXBELd224OQFLwxiIylWtAkZpe/Y9o
IGEEz5OX7PA/b6t5OIEo98G0pGNXvMiPcm+HSBUCgYAHpuM8fKiRCoznoDrBbGmA
FVokdvKocAchN4IT2S0ZBmAOg2k8o/28WncRRTdB0+LNuNsnBL+ng7FEzzb72xy4
ty/KdjnXOPizACQ8uhKi6iMkFBc/ErqTrJrfcY/3kBnDC2tS2e9z4X101cib/iYW
w9tUwI961IO8hgFQyIb8fQKBgQCOg3ZyqYSmhSqE1cHM66cs2iVnSRMDXMVFkEPg
74iIDv35Ty1fNeaDXk5TeYMk0HynKnQxUoaW8du0NyrZrIVbWuLgS1peL/tTjFCP
jWJxrfmd50q8/8Jiy9ZO4cLtbqfP/2JMl5fa+3PfKFiqr16lfoYs5K6XunOfegyl
Hr1MpQKBgFZ84EaudGufLx1Bo0+v+FcOFfbQxEmkkyJpQwoi6Dvmh/MTe3TNegaY
MBf7rm6l65ZqfBMAwRDjE/dhVwRNpd9jRzPVBVyWRZOJkd63n/ENPdIiUrFdvgIt
SFNKk00LvLk4VgWBtUbK9wdk8GQHBrd1mNXnni2x0u0VWLDnW5Zs
-----END RSA PRIVATE KEY-----

The test data being signed is(already base64 encoded):
Code:
eyJ1c2VyaWQiOiJcdTAwMGFkOTQ2ZWQ2MDFmMTNhNDZmNjU1YjUwODM4N2FmZTc2OWYzNTNiMzk1MmY3YTMzOWE4Mjc3ZTdmMTlkYTU4NGQ4XHUwMDBhIiwibm9uY2UiOjg2MTU2NjE5NTE2NX0=


We're using SHA512 as the padding digest.

Signature(base64 encoded) should be:

Code:
AZIigvzu0G2BG/RpDz05qZZctQvzTGNOiOJzziL1+eQEU42cwp/LPOv+6DwMgDIIf2/DAHD+pe7bsxIWftlr65z1bRTYdQ+K+VA0fC6m36muny3NLsKl4hrqIVVWQsTZwbUqJcOvYaNcYMaXr05hTMKC4XAkqKNSqLBOc41k7vU8V6duYwndal7rZiWvso+cH0HxffJszLREUbamMtNBapmhXJCsn2PafQ+RyFj5VnJPYe5MIp/d86yco2q1PC2jLyySxH2kma6d1dq/yxgFiTiABT80w7/9GPlE+cNFIuclEeeYZyo+3r1R7Lgqhnr98MGC7dGjrW5BK5zSRHjgBw==

What I keep getting is:
Code:
GSIoL87tBtgRv0aQ89OamWXLUL80xjTojic84i9fnkBFONnMKfyzzr/ug8DIAyCH9vwwBw/qXu27 MSFn7Za+uc9W0U2HUPivlQNHwupt+prp8tzS7CpeIa6iFVVkLE2cG1KiXDr2GjXGDGl69OYUzCgu FwJKijUqiwTnONZO71PFenbmMJ3Wpe62Ylr7KPnB9B8X3ybMy0RFG2pjLTQWqZoVyQrJ9j2n0Pkc hY+VZyT2HuTCKf3fOsnKNqtTwtoy8sksR9pJmundXav8sYBYk4gAU/NMO//Rj5RPnDRSLnJRHnmG cqPt69Uey4KoZ6/fDBgu3Ro61uQSuc0kR44A

Get the function sign_and_encode(data,private_key) to return the correct output, the fuction (and all it's dependencies) can be found here http://dev.glbse.com:4567/rsa.html  just view source. Time is very important, we need to move on ASAP.

If needs be you can use another Javscript RSA library if the one being used is simply broken.

Note:updated to remove linebreaks from the base64 endoded signature


Title: Re: Paying to get RSA signing working in Javascript
Post by: de4l on May 23, 2011, 08:18:13 AM

Signature(base64 encoded) should be:

Code:
AZIigvzu0G2BG/RpDz05qZZctQvzTGNOiOJzziL1+eQEU42cwp/LPOv+6DwM\ngDIIf2/DAHD+pe7bsxIWftlr65z1bRTYdQ+K+VA0fC6m36muny3NLsKl4hrq\nIVVWQsTZwbUqJcOvYaNcYMaXr05hTMKC4XAkqKNSqLBOc41k7vU8V6duYwnd\nal7rZiWvso+cH0HxffJszLREUbamMtNBapmhXJCsn2PafQ+RyFj5VnJPYe5M\nIp/d86yco2q1PC2jLyySxH2kma6d1dq/yxgFiTiABT80w7/9GPlE+cNFIucl\nEeeYZyo+3r1R7Lgqhnr98MGC7dGjrW5BK5zSRHjgBw==


I'm looking through everything but so far, this does not appear to be a valid base-64 string for me at least

ps. or is the implication that this was the (RSA encoded (base-64 encoded(data)) and not (base64(rsa(base64(data))))


Title: Re: Paying to get RSA signing working in Javascript
Post by: Nefario on May 23, 2011, 08:28:28 AM
Sorry, that seems to be including linebreaks, here it is without the linebreaks(\n).

Code:
AZIigvzu0G2BG/RpDz05qZZctQvzTGNOiOJzziL1+eQEU42cwp/LPOv+6DwMgDIIf2/DAHD+pe7bsxIWftlr65z1bRTYdQ+K+VA0fC6m36muny3NLsKl4hrqIVVWQsTZwbUqJcOvYaNcYMaXr05hTMKC4XAkqKNSqLBOc41k7vU8V6duYwndal7rZiWvso+cH0HxffJszLREUbamMtNBapmhXJCsn2PafQ+RyFj5VnJPYe5MIp/d86yco2q1PC2jLyySxH2kma6d1dq/yxgFiTiABT80w7/9GPlE+cNFIuclEeeYZyo+3r1R7Lgqhnr98MGC7dGjrW5BK5zSRHjgBw==


Title: Re: Paying to get RSA signing working in Javascript
Post by: Jere.Jones on May 23, 2011, 08:47:45 AM
What is your source for the expected output?

Jere


Title: Re: Paying to get RSA signing working in Javascript
Post by: Nefario on May 23, 2011, 08:55:52 AM
What is your source for the expected output?

Jere

I've been using ruby's interface to openssl

If you've got ruby installed launch irb.

Code:
require 'openssl'
require 'base64'

privkey="privatekeytext"
data="my data string"
private_key = OpenSSL::PKey::RSA.new(privkey)
b64sig=Base64.encode64(private_key.sign( OpenSSL::Digest::SHA512.new, data))

I know it works as I've been using it on glbse since before we launched.


Title: Re: Paying to get RSA signing working in Javascript
Post by: Nefario on May 23, 2011, 09:04:39 AM
You can actually just use the source from the page linked(it's a static page), if it works with that then it should just plain old work, so a link to a html page with all the js source in it would be fine(essentially a copy of the one I linked to).


Title: Re: Paying to get RSA signing working in Javascript
Post by: weweritz on May 23, 2011, 09:23:52 AM
Funny thing, this.
The problem is in the rsa.signString function that returns the hex value of the signature. Javascript incorrectly discards the leading zero (1922282fceed0... instead of 01922282fceed0...) and when you convert this to binary and then base64encode it, naturally, everything goes wrong. With the extra zero, the output is as specified.



Title: Re: Paying to get RSA signing working in Javascript
Post by: Nefario on May 23, 2011, 09:28:42 AM
Funny thing, this.
The problem is in the rsa.signString function that returns the hex value of the signature. Javascript incorrectly discards the leading zero (1922282fceed0... instead of 01922282fceed0...) and when you convert this to binary and then base64encode it, naturally, everything goes wrong. With the extra zero, the output is as specified.



Nice, you found a bug(not my code). Do you know if a leading 0 needs to be added with all output or just this instance?


Title: Re: Paying to get RSA signing working in Javascript
Post by: de4l on May 23, 2011, 09:38:17 AM
you could also just un-comment the base-64 output built into rsa.js and use that instead of the additional (lossy) conversion steps


Title: Re: Paying to get RSA signing working in Javascript
Post by: weweritz on May 23, 2011, 09:39:52 AM
The hex that the stringSign function returns should be 512 characters long. If it is any shorter, prepend the number of zeroes that are missing;

something along the lines
Code:
while ( String( hSig ).length < 512 ) hSig = "0" + String( hSig );

should work.


Title: Re: Paying to get RSA signing working in Javascript
Post by: mikegogulski on May 23, 2011, 09:46:04 AM
I succeeded in getting "shitassfuck" as output from your test script! :D


Title: Re: Paying to get RSA signing working in Javascript
Post by: Jere.Jones on May 23, 2011, 09:49:49 AM
The hex that the stringSign function returns should be 512 characters long. If it is any shorter, prepend the number of zeroes that are missing;

something along the lines
Code:
while ( String( hSig ).length < 512 ) hSig = "0" + String( hSig );

should work.
Unfortunately, that won't work because the bad version is 2 characters short.  A zero on the front and a 7 on the back.

There's a bug in bnToString(b) in jsbn.js that needs to be fixed.

Jere


Title: Re: Paying to get RSA signing working in Javascript
Post by: arturh on May 23, 2011, 10:06:55 AM
Add needed zeroes to s:

s = new Array(257-s.length).join("0") + s;


Title: Re: Paying to get RSA signing working in Javascript
Post by: Nefario on May 23, 2011, 10:18:01 AM
I succeeded in getting "shitassfuck" as output from your test script! :D

Thats more than the stated requirements  :P


Title: Re: Paying to get RSA signing working in Javascript
Post by: Jere.Jones on May 23, 2011, 10:20:35 AM
Here you go:  Replace your jsbn.js with the one located at http://jere.us/jsbn.zip and you'll be good to go.

It properly fixes the bnToString so that it outputs full hex bytes instead of skipping the first 4 bits when there isn't data for them.

Jere


Title: Re: Paying to get RSA signing working in Javascript
Post by: Jere.Jones on May 23, 2011, 10:42:27 AM
I just put up an improved version.  You probably want to download it again.  The previous version had issues with IE.  This one works correctly in IE although doing RSA in IE is annoying. :)

http://jere.us/jsbn.zip

Jere


Title: Re: Paying to get RSA signing working in Javascript
Post by: Nefario on May 23, 2011, 10:42:51 AM
I succeeded in getting "shitassfuck" as output from your test script! :D

So to actually test if the whole thing properly works you would change

Code:
//sedData('test',{});

to

Code:
sendData("account/balance",{});

And the result from the server should be the balance(base64 encoded) if it works, otherwise it's a base64 encoded error(probably bad signature).


Title: Re: Paying to get RSA signing working in Javascript
Post by: Nefario on May 23, 2011, 10:47:20 AM
Actually the update(above) can be seen in http://dev.glbse.com:4567/rsa.html

Jere.Jones, problem seems to persist. Am going to manually check now.


Title: Re: Paying to get RSA signing working in Javascript
Post by: mikegogulski on May 23, 2011, 10:48:31 AM
I succeeded in getting "shitassfuck" as output from your test script! :D

So to actually test if the whole thing properly works you would change

Code:
//sedData('test',{});

to

Code:
sendData("account/balance",{});

And the result from the server should be the balance(base64 encoded) if it works, otherwise it's a base64 encoded error(probably bad signature).


... and here I kinda liked the "shitassfuck" API :)


Title: Re: Paying to get RSA signing working in Javascript
Post by: graingert on May 23, 2011, 10:52:28 AM
perhaps you should tell stanford to fix their library?

http://www-cs-students.stanford.edu/~tjw/jsbn/


Title: Re: Paying to get RSA signing working in Javascript
Post by: Nefario on May 23, 2011, 10:59:32 AM

... and here I kinda liked the "shitassfuck" API :)


That was to solve the problem of why was my script not posting to the server, turned out to be the no-cross domain posting in javascript for ajax.

Jere.Jones, manual check confirms the output isn't correct.

graingert, yeah that will happen but how long's that going to take, I need this fixed now, and am willing to pay. The fixer can then contact the stanford boys, and get their fix in (and get the credit for doing so).


Title: Re: Paying to get RSA signing working in Javascript
Post by: Jere.Jones on May 23, 2011, 11:01:24 AM
Actually the update(above) can be seen in http://dev.glbse.com:4567/rsa.html

Jere.Jones, problem seems to persist. Am going to manually check now.

The suspect that the problem on your page is the way <div id="pub_id"> is laid out.  The '\n's are included in the public_id.  Try removing the line feeds.

Jere


Title: Re: Paying to get RSA signing working in Javascript
Post by: Jere.Jones on May 23, 2011, 11:06:38 AM
Jere.Jones, manual check confirms the output isn't correct.
Can you be more specific?  The output of what wasn't correct?

Also, I sent you a PM.

Jere


Title: Re: Paying to get RSA signing working in Javascript
Post by: Nefario on May 23, 2011, 11:25:33 AM
problem probably isnt the userid(will check later, busy for the next couple of hours), as it would throw up a wrong userid error(normally it would).

So I checked the data and signature that was sent to the server (using the updated lib), and then manually (using irb)checked what the signature would should have been for that private key signing the same data, and compared the results, and indeed the signatures are not the same. This is the result when we run the sendData function to account/balance on the server(that is the signature fails the verification because its not what it should be).

Unless someone else has some other ideas?

The best example to see how this should work is to have a look at te source of the glbse client bmc.py


Title: Re: Paying to get RSA signing working in Javascript
Post by: Jere.Jones on May 23, 2011, 01:14:54 PM
Then I would need more data to continue troubleshooting.  The updated jsbn.js fixes sign_and_encode so that given the input you provided, it returns the output you expect.

Jere


Title: Re: Paying to get RSA signing working in Javascript
Post by: Jere.Jones on May 23, 2011, 02:02:26 PM
Just for giggles, I put up this page: http://jere.us/rsa_test.html

It has two forms on it that both submit to dev glbse account balance.  The first one submits the data you provided in your first post.  The second one calculates the form data. 

To use the top form:
1. Click the top "Submit" button
2. Notice error page

To use the bottom form:
1. Enter a nonce or click the "Create Nonce" button
2. Click the "Calculate Data and Sig" button
3. Notice that the data and sig are available for inspection
4. Click the bottom "Submit"
5. Notice error page

For my tests the error pages are the same.  Line 58 of base64.rb calls an unknown method.  You have to fix that before I can continue.

Is my page doing anything it should not?  I know the second form submits some stuff it doesn't have to, but that should be ignored anyway so it shouldn't cause a problem.  Or at least, not the problem I'm seeing.

Jere


Title: Re: Paying to get RSA signing working in Javascript
Post by: Nefario on May 23, 2011, 03:21:42 PM
Ill have to wait until tomorrow.


Title: Re: Paying to get RSA signing working in Javascript
Post by: unfinishe on May 24, 2011, 08:35:58 AM
I confused myself pretty quickly trying to figure out what's going on, so I don't know whether this has anything to do with the problem. Earlier I was trying to replicate the original hash by using openssl on the command line. I first digested the data using sha512, then signed with the private key, and then encoded into base64, but the signature didn't match.

So I looked around and found this thread: http://www.ruby-forum.com/topic/77070
It seems that the sign function in ruby does something different than doing it step by step with openssl like I was trying to. Instead, the private_encrypt function seems to do the trick. Perhaps something like this would work better

Code:
private_key = OpenSSL::PKey::RSA.new(privkey)
data_digest = OpenSSL::Digest::SHA512.hexdigest(data)
b64sig=Base64.encode64(private_key.private_encrypt(data_digest))


Title: Re: Paying to get RSA signing working in Javascript
Post by: Nefario on May 25, 2011, 11:44:21 AM
Just for giggles, I put up this page: http://jere.us/rsa_test.html

It has two forms on it that both submit to dev glbse account balance.  The first one submits the data you provided in your first post.  The second one calculates the form data. 

To use the top form:
1. Click the top "Submit" button
2. Notice error page

To use the bottom form:
1. Enter a nonce or click the "Create Nonce" button
2. Click the "Calculate Data and Sig" button
3. Notice that the data and sig are available for inspection
4. Click the bottom "Submit"
5. Notice error page

For my tests the error pages are the same.  Line 58 of base64.rb calls an unknown method.  You have to fix that before I can continue.

Is my page doing anything it should not?  I know the second form submits some stuff it doesn't have to, but that should be ignored anyway so it shouldn't cause a problem.  Or at least, not the problem I'm seeing.

Jere

Hey Jere, the error you were getting is because you were submitting the data wrong.

There are only 2 post fields data, signature
data is the base encoded json string containing all the data elements (nonce, use_id etc.) while signature is the base64 encoded signature.

The reason you were getting that error was because the app was looking for the post field "signature" and that was nil, so of course you can't base64 decode nil can you. Ah, these errors are much nicer in a browser than on the command line.


Title: Re: Paying to get RSA signing working in Javascript
Post by: Jere.Jones on May 25, 2011, 02:49:57 PM
Well that makes a difference. :)

Changing the field name from "sig" to "signature" does make a difference and allows the first form to succeed.

A little bit of testing showed that I needed to strip the line feeds and carriage returns from data before signing and encoding it.  Once I did that, it seems to be working beautifully.  Updated code is at http://jere.us/rsa_test.html

Thanks!
Jere

EDIT:
A balance of 1900000009.  Is that in bitcoins or satoshis?  If it's in bitcoins, can I have that account? ;)


Title: Re: Paying to get RSA signing working in Javascript
Post by: Jere.Jones on May 25, 2011, 03:20:34 PM
perhaps you should tell stanford to fix their library?

http://www-cs-students.stanford.edu/~tjw/jsbn/
Done.  I even included the reasoning and the fix. :-)

Jere