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

Multiplatform #14

Draft
wants to merge 21 commits into
base: main
Choose a base branch
from
Draft

Multiplatform #14

wants to merge 21 commits into from

Conversation

luca992
Copy link
Contributor

@luca992 luca992 commented Apr 4, 2022

This isn't done yet, I still have to clean it up.

But, I ported the project over to using the multiplatform plugin. Added js and native(mac, ios) targets. Updated all dependencies and swapped use of moshi for kotlinx serialization

All targets seem to be working. I used okio's multiplatform sha and hmac sha implementations to replace the use of java specific ones.

The only thing I'm sure unsure about is switching from java Locale to https://github.com/fluidsonic/fluid-locale . I think it accomplishes the same thing?

@ccjernigan
Copy link
Contributor

@luca992 Thank you for the pull request. Multiplatform is an important feature that we're also keeping an eye on internally, so the effort here is appreciated!

The prior maintainer of this project left Zcash a few months ago, and I've just started as the new maintainer about 2 weeks ago. With the transition, the notification of your draft PR was missed. I'll be looking at reviewing and providing feedback to this PR very soon.

@luca992
Copy link
Contributor Author

luca992 commented Apr 20, 2022

I'm probably going to just move the test json to a string... if that's cool. I'm using moko-resources to load the file in a multiplatform way. But it appears that moko-resources doesn't support resources in the /commonTest/resources folder atm.

@ccjernigan ccjernigan self-requested a review April 21, 2022 19:09
Copy link
Contributor

@ccjernigan ccjernigan left a comment

Choose a reason for hiding this comment

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

Thanks for this pull request—I appreciate all the effort that went into these great suggested changes here! You might have noticed that we're also taking some steps towards being more multiplatform ready in our other Android projects, so this is something that I think is important.

To speed up the process of incorporating these changes, I'm going to recommend that we break this down into multiple steps as a series of PRs. That will help create a secure and robust multiplatform implementation as quickly as possible.

This is the rough roadmap I have in mind:

  1. Apply Multiplatform Kotlin Plugin: Modernize the build scripts and refactor to be an enabler for multiplatform, but only with a JVM target. Code lives in jvmMain/jvmTest. I've created Modernize build #32 that addresses this.
  2. Multiplatform tests: Port tests to be multiplatform, by dropping use of a JSON resource file. Move tests to commonTest source directory. Tests still only run on JVM, because no other targets added yet. This should be a quick extraction from this existing PR, once I get PR Modernize build #32 merged in the next few days.
  3. Refactor for JVM-only multiplatform: Move most code into commonMain, add expect classes and methods, and add actual classes/methods in the jvmMain source directory. To library consumers, this should behave exactly as before but it sets up the ability to then add additional multiplatform implementations with minimal refactoring. This should also be a somewhat quick extraction from this PR.
  4. Add additional platforms one-by-one (e.g. JS, native). This will be the slowest step, as we'll have to do security reviews of the platform-specific implementations. As a general policy, we want to avoid third party libraries so this will require some careful consideration on what we do for the SHA256 implementation.

I have added some comments inline. I don't necessarily expect to see another commit to this PR addressing those unless you'd like the feedback and iteration. We won't merge this PR but we can quickly merge independent PRs for steps 1, 2, and 3, and then we'll have to slow down a bit for 4.

Do you have a particular non-JVM platform that's especially important to you first? Knowing that can also help focus our discussion around 4 as well.

lib/karma.config.d/moko-resources-generated.js Outdated Show resolved Hide resolved
@@ -1,7 +1,7 @@
# Publishing : Required
GROUP=cash.z.ecc.android
POM_ARTIFACT_ID=kotlin-bip39
VERSION_NAME=1.0.2
VERSION_NAME=1.0.2-SNAPSHOT
Copy link
Contributor

Choose a reason for hiding this comment

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

Just an FYI I think we'll end up moving towards 2.0.0 to support multiplatform, as there are a few breaking API changes to make.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah, didn't mean to commit that. Just needed a unique version for local haha

gradle.properties Outdated Show resolved Hide resolved
@@ -1,3 +1,6 @@
package cash.z.ecc.android.bip39

const val BIP0039TestValues = """
Copy link
Contributor

Choose a reason for hiding this comment

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

Moving this from a file resource is a good improvement.

Honestly, I don't think it needs to be a json string though. This test data could easily be a list of data class instances so that we don't even have to use Kotlinx serialization for the JSON.


actual class SecureRandom {

actual fun nextBytes(bytes: ByteArray){
Copy link
Contributor

Choose a reason for hiding this comment

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

Until we have a secure source of randomness for each supported platform, this should block merging this PR.

It looks like KotlinJS for browser has a Crypto API that it can use. I think last time I checked, having a different implementation between Node and Browser was painful, so we might need to think about a solution there.

Thoughts on native?

Copy link
Contributor Author

@luca992 luca992 Apr 21, 2022

Choose a reason for hiding this comment

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

js would be easy enough as you said. would probably have to use cinterop with these system apis: https://libsodium.gitbook.io/doc/generating_random_data ... or...

Copy link
Contributor Author

@luca992 luca992 Apr 21, 2022

Choose a reason for hiding this comment

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

If you're not opposed to adding another dependency:
https://github.com/ionspin/kotlin-multiplatform-libsodium
would work for a secure random generator

Copy link
Contributor Author

@luca992 luca992 Apr 21, 2022

Choose a reason for hiding this comment

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

or if you had a c library in mind to use with cinterop, checkout how I integrated building this c library libaes_siv for each target in my build.gradle for my project secretk

Copy link
Contributor

Choose a reason for hiding this comment

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

We don't want to bring in third party dependencies. cinterop with what's available on a native platform is reasonable, as that's effectively what we're doing with SecureRandom from the Java side.

Copy link
Contributor

Choose a reason for hiding this comment

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

Apple already has API’s for generating secure random data, and the existing native implementation done by Luca is probably sufficient to not need the Apple-specific API.

The hold up on merging this pull request is that it needs to be divided into smaller PRs that we can review. As one large PR, it will take a very long time to get through our review process since multiple security experts in different platforms need to be involved.

Copy link
Contributor Author

@luca992 luca992 Feb 7, 2023

Choose a reason for hiding this comment

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

@ccjernigan I already published my own fork to my own repo so this really isn't my top priority atm. But I might be able to break this pr up as you requested soon. Has anything changed with how you want it done since: #14 (comment) ?

Copy link
Contributor

Choose a reason for hiding this comment

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

I saw your version got published a while back, and I'm glad you were able to leverage our project to help your own efforts move forward 🎉.

What I wrote before is still pretty accurate. A few minor notes since then:

  • We had another contributor move the tests from jvmTest to commonTest, so that part is done already.
  • I'd suggest starting with the JVM-only multiplatform refactor. It should effectively be a no-op, and I should be able to review/merge that very quickly.
  • For the native/JS targets, it might be faster to split that into a PR for each (one for native, one for JS) because then our team can review each independently.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

JVM-only multiplatform refactor done #158

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks—I'm doing the review for the JVM-only changes ASAP.

There's a new JetBrains blog post relevant for which native targets we choose to configure: https://blog.jetbrains.com/kotlin/2023/02/update-regarding-kotlin-native-targets/

@luca992
Copy link
Contributor Author

luca992 commented Apr 21, 2022

Do you have a particular non-JVM platform that's especially important to you first? Knowing that can also help focus our discussion around 4 as well.

iOS is most important. Then probably macOS and linux. But if there's no limiting dependencies, personally I would just target everything, it's not any extra work.

@luca992
Copy link
Contributor Author

luca992 commented Apr 26, 2022

I'm confused. If I wanted to help contribute to your roadmap, should I make a new pr off of main. Or refactor this PR off of main?

luca992 added 7 commits April 26, 2022 01:00
java secure random for jvm
/dev/urandom for native
crypto.getRandomValues for js
MessageDigest for jvm
okio for others
Pbkdf2Sha512 jvm uses javax crypto as before
Pbkdf2Sha512 non-jvm uses okio
@luca992
Copy link
Contributor Author

luca992 commented Apr 26, 2022

Think I fixed the majority of your concerns @ccjernigan take a look

luca992 added a commit to eqoty-labs/secretk that referenced this pull request Apr 26, 2022
@ccjernigan
Copy link
Contributor

I'm confused. If I wanted to help contribute to your roadmap, should I make a new pr off of main. Or refactor this PR off of main?

My suggestion would be:

  1. Create a new PR off of main (since we just finished fixing up our build scripts). We do have a few additional minor changes pending review that you can see open, but they shouldn't create too many merge conflicts.

  2. Split your original PR into multiple steps. I can quickly review and merge a single or two PRs with changes for these two items described originally:

  1. Multiplatform tests: Port tests to be multiplatform, by dropping use of a JSON resource file. Move tests to commonTest source directory. Tests still only run on JVM, because no other targets added yet. This should be a quick extraction from this existing PR, once I get PR Modernize build #32 merged in the next few days.
  2. Refactor for JVM-only multiplatform: Move most code into commonMain, add expect classes and methods, and add actual classes/methods in the jvmMain source directory. To library consumers, this should behave exactly as before but it sets up the ability to then add additional multiplatform implementations with minimal refactoring. This should also be a somewhat quick extraction from this PR.
  1. For native and JS targets, the SecureRandom implementation is looking good. We'll still have to come up with a replacement for Okio that doesn't rely on a third party library. We'll also have to get a member of our DevSecOps team to participate in the review of the JS and Native platform code for the hashing and SecureRandom code. This will take more time.

I'm suggesting splitting up the work so that we can quickly merge the things that are low risk (multiplatform tests and a JVM-only multiplatform friendly refactoring) versus the JS and Native implementations for the security-related stuff.

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.

3 participants