-
Notifications
You must be signed in to change notification settings - Fork 9
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
base: main
Are you sure you want to change the base?
Multiplatform #14
Conversation
Todo: get non-jvm tests running. They use kotest. I can't get the tests to run on non-jvm for some reason
use RELEASE_SIGNING_ENABLED=false More info: https://github.com/vanniktech/gradle-maven-publish-plugin#signing
@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. |
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. |
added some moko-resources related warning workarounds
There was a problem hiding this 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:
- 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. - 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. - Refactor for JVM-only multiplatform: Move most code into
commonMain
, addexpect
classes and methods, and addactual
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. - 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/src/commonMain/kotlin/cash/z/ecc/android/bip39/Mnemonics.kt
Outdated
Show resolved
Hide resolved
lib/gradle.properties
Outdated
@@ -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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
lib/src/commonMain/kotlin/cash/z/ecc/android/bip39/Mnemonics.kt
Outdated
Show resolved
Hide resolved
lib/src/commonMain/kotlin/cash/z/ecc/android/bip39/Mnemonics.kt
Outdated
Show resolved
Hide resolved
@@ -1,3 +1,6 @@ | |||
package cash.z.ecc.android.bip39 | |||
|
|||
const val BIP0039TestValues = """ |
There was a problem hiding this comment.
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){ |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) ?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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/
lib/src/jvmMain/kotlin/cash/z/ecc/android/random/SecureRandom.kt
Outdated
Show resolved
Hide resolved
lib/src/nonJvmMain/kotlin/cash/z/ecc/android/crypto/PBEKeySpec.kt
Outdated
Show resolved
Hide resolved
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. |
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? |
java secure random for jvm /dev/urandom for native crypto.getRandomValues for js
MessageDigest for jvm okio for others
…able all native targets
Pbkdf2Sha512 jvm uses javax crypto as before Pbkdf2Sha512 non-jvm uses okio
Think I fixed the majority of your concerns @ccjernigan take a look |
…es are accepted KHash PR: komputing/KHash#23 kotlin-bip39: Electric-Coin-Company/kotlin-bip39#14
My suggestion would be:
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. |
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?