Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test JS to Go connections with both RSA and Secp256k1 keys #21

Merged
merged 3 commits into from
Jul 15, 2019

Conversation

aknuds1
Copy link
Contributor

@aknuds1 aknuds1 commented Jul 3, 2019

As a starting point for solving #20, test JS -> Go connections for both RSA and ECDSA keys.

I'm open to discuss alternative ways of parameterizing the tests over key type. I'm used to testing with AVA, so not sure how to best implement data driven testing with Mocha :)

@aknuds1 aknuds1 force-pushed the bugfix/test-ecdsa-keys branch 5 times, most recently from 2e718c4 to 3558e77 Compare July 4, 2019 07:43
src/daemon.js Outdated Show resolved Hide resolved
src/daemon.js Outdated Show resolved Hide resolved
// Start Daemons
before(async function () {
this.timeout(20 * 1000)
return spawnDaemons(2, [{type: 'js', keyType}, {type: 'go', keyType}])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we change how start is called we can leverage the third param of spawnDaemons to pass { id: keyPath }

@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 4, 2019

@jacobheun In my master branch, where I use my own versions of various libp2p dependencies (due to bugs I've fixed), I've got to the point of being able to launch JS and Go daemons, but the RSA test fails in a way I don't understand:

1) connecting js peer to go peer
       with RSA keys
         should work:
     Error: Key or message is invalid!: error:04075070:rsa routines:RSA_sign:digest too big for rsa key
      at createError (node_modules/err-code/index.js:4:44)
      at Client.connect (node_modules/@arve.knudsen/libp2p-daemon-client/src/index.js:168:13)
      at processTicksAndRejections (internal/process/task_queues.js:82:5)
      at async performTest (test/connect/js2go.js:47:3)
      at async Context.<anonymous> (test/connect/js2go.js:72:7)

Are you able to understand what would cause this issue? I'm guessing the Go daemon key is the problematic one, but I've generated it with crypto.GenerateRSAKeyPair and 2048 bits which seems to be what the daemon also does, so I don't see how to fix this. If you could help me out with this one, I'd appreciate it very much :)

@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 4, 2019

@jacobheun Also if you don't mind, I can update this PR to use my forked dependencies, so you we can get the tests running. We should revert to non-forked dependencies before merging this PR of course.

@aknuds1 aknuds1 changed the title Test JS to Go connections with both RSA and ECDSA keys WIP: Test JS to Go connections with both RSA and ECDSA keys Jul 4, 2019
@vasco-santos
Copy link
Member

@jacobheun Also if you don't mind, I can update this PR to use my forked dependencies, so you we can get the tests running. We should revert to non-forked dependencies before merging this PR of course.

@aknuds1 yes, feel free to install in package.json the dependencies pointing to your branches

@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 4, 2019

@jacobheun @vasco-santos I pushed package.json with my forked dependencies.

I would suggest you check the RSA test in test/connect/js2go.js in isolation, to figure out why the RSA key error occurs.

@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 4, 2019

@vasco-santos @jacobheun Never mind, I found out what the issue was with the RSA key - I had messed up in my key generator and used 256 bits for both RSA and ECDSA :/ Sorry!

@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 4, 2019

My current problem is that the test client can't connect to the JS daemon in the RSA test, although connecting to the Go daemon works. It seems to hang on trying to obtain a connection to /tmp/p2pd-0.sock. Have to go now, so will have to pick up debugging again later.

@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 5, 2019

Fixed the issue I was having, so the RSA test works. ECDSA test fails, but the response is empty so can't tell why yet.

@jacobheun
Copy link
Contributor

FYI, if you rebase CI should stop failing commitlint for you, I removed that from the build since it's annoying :)

I assume ECDSA is likely failing because JS probably just assumes it's being given an RSA key at the moment, so when it goes to do actual encryption it fails.

@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 7, 2019

@jacobheun @vasco-santos I figured out what makes SECP256k1 keys incompatible between Go and JS daemons. The Go daemon calculates a different peer ID, due to the AdvancedEnableInlining option in github.com/libp2p/go-libp2p-core/peer. I.e., since the SECP256k1 public key is less than 42 bytes, the Go daemon uses the multihash ID algorithm to compute the PK digest and thus produces a different ID as the JS daemon doesn't have this logic.

When the JS daemon calculates a different peer ID from the Go daemon, on SECIO handshake, it produces an error (dialed to the wrong peer, Ids do not match).

What do you think, is it a bug that the Go and JS daemons don't agree on the logic for producing peer IDs?

@tobowers
Copy link

tobowers commented Jul 8, 2019

Hi hi, Adding this for context too: libp2p/specs#138

@aknuds1 aknuds1 force-pushed the bugfix/test-ecdsa-keys branch 2 times, most recently from a1b072c to 1720541 Compare July 8, 2019 12:47
@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 8, 2019

@vasco-santos @jacobheun I worked around the problem I found of the Go daemon producing incompatible peer IDs by forking go-libp2p-dep, and making it use a version of go-libp2p-daemon that allows you to disable PK inlined peer IDs. The secp256k1 test now works :)

The tests fail on Windows, due to what looks like a timeout getting the go-libp2p-daemon archive for Windows off of IPFS. I am serving it from a DigitalOcean VM, but it's really slow to get hold of for some reason.

@aknuds1 aknuds1 changed the title WIP: Test JS to Go connections with both RSA and ECDSA keys WIP: Test JS to Go connections with both RSA and Secp256k1 keys Jul 8, 2019
@jacobheun
Copy link
Contributor

@Stebalien @raulk did we come to a resolution on key inlining in go? I know js will need some updates for non RSA keys, but I'm not sure where/if we came to a resolution for handling inlining going forward.

@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 9, 2019

@jacobheun On our side (Quorum Control) in the meantime, I made another workaround by modifying libp2p-secio to handle also peer IDs with inlined public key on protocol handshake (i.e. if the remote ID doesn't match, it tries also inlining the PK). This seems to work! Is this a possible (transitional) fix, instead of changing the Go logic?

@jacobheun
Copy link
Contributor

@aknuds1 can you open up a Draft PR of that over at libp2p-secio and we can talk through that potential solution there?

@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 9, 2019

@aknuds1 can you open up a Draft PR of that over at libp2p-secio and we can talk through that potential solution there?

@jacobheun Will do!

@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 11, 2019

@jacobheun @vasco-santos I could use your advice on what's the best solution to harmonize Go and JS implementations of libp2p with regards to calculation of peer ID in case of Secp256k1 keys?

So far I tried to build robustness into both libraries, so that on connection JS libp2p will test if the remote's peer ID is calculated with the identity scheme and vice versa for Go libp2p. However, it doesn't work perfectly since for example when you connect a JS peer to a Go peer and you list the peers of the Go peer, it will give you a different ID for the JS peer (since it uses the identity scheme to calculate it from the given public key).

Given the problem described above, I wonder if it would be best to modify JS libp2p to also calculate peer IDs with identity scheme if the PK is shorter than 43 bytes, since it would then behave the same as the Go implementation.

@jacobheun
Copy link
Contributor

Given the problem described above, I wonder if it would be best to modify JS libp2p to also calculate peer IDs with identity scheme if the PK is shorter than 43 bytes, since it would then behave the same as the Go implementation.

I think we'll need to do this for now so that we match go and can leverage the keys. This may cause issues in the future if/when we upgrade how this is calculated, but this will need to be done in go anyway. I'd rather us having a working implementation now and cross that bridge when we come to it than to delay this until that change happens, since that is currently an unknown.

@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 11, 2019

@jacobheun Thanks for the helpful answer! I'm going to prototype porting Go's peer ID algorithm to JS and see how it goes.

@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 11, 2019

Using my modified peer-id package, this scenario looks to be fixed for me locally at least.

@aknuds1 aknuds1 changed the title WIP: Test JS to Go connections with both RSA and Secp256k1 keys Test JS to Go connections with both RSA and Secp256k1 keys Jul 11, 2019
@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 11, 2019

@vasco-santos @jacobheun Can you please blow away the Travis dependency cache? It works locally, but I think the dependencies must be updated.

@Stebalien
Copy link
Member

@jacobheun my current plan is to leave it as it is and to try to find a way to help OpenBazaar upgrade. At this point, too many are relying on key inlining to easily revert it. Thoughts @raulk?

@jacobheun
Copy link
Contributor

@aknuds1 cache cleared and tests are passing here now 👍

@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 11, 2019 via email

@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 12, 2019

I revised according to @jacobheun's suggestions, please have another look.

Copy link
Contributor

@jacobheun jacobheun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just two nits that I think could be helpful for readability if the tests are expanded in the future. Other than that, this LGTM.

test/utils/spawnDaemons.js Outdated Show resolved Hide resolved
test/utils/spawnDaemons.js Outdated Show resolved Hide resolved
aknuds1 and others added 2 commits July 12, 2019 11:04
Co-Authored-By: Jacob Heun <jacobheun@gmail.com>
Co-Authored-By: Jacob Heun <jacobheun@gmail.com>
@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 12, 2019

@jacobheun Cool, committed your suggestions.

daemon.stderr.on('data', (data) => {
if (!data.toString().includes('Warning')) {
return reject(data.toString())
daemon.on('exit', (code, signal) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figure it's more robust to fail if the daemon fails, instead of when it simply prints a warning?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with that!

@vasco-santos
Copy link
Member

@aknuds1 I will not merge this PR yet because I have been experiencing issues with the CI for js-libp2p-daemon for the following test: should be able to load a Secp256k1 private key:

Can you have a look as that might have impact on this PR?

@aknuds1
Copy link
Contributor Author

aknuds1 commented Jul 15, 2019

@aknuds1 I will not merge this PR yet because I have been experiencing issues with the CI for js-libp2p-daemon for the following test: should be able to load a Secp256k1 private key:

Can you have a look as that might have impact on this PR?

@vasco-santos Please have a look at this PR.

@vasco-santos
Copy link
Member

I haven't noticed your PR! We are good to go here

Copy link
Member

@vasco-santos vasco-santos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@vasco-santos vasco-santos merged commit 28b2d80 into libp2p:master Jul 15, 2019
@aknuds1 aknuds1 deleted the bugfix/test-ecdsa-keys branch July 15, 2019 10:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants