Closed enclave-alistair closed 1 month ago
I didn't think the changes since the last release were significant enough for a new release, but I've done a new pre-release now. If all looks good, I could do a new release soon.
Having iOS on the official support list would be nice. However, I still haven't been able to fully figure out what is needed for this. Are the changes in 114231a21aa75c5c90ea8e95da2777eeadfffe78 enough or is there anything else that should be done in NSec (or libsodium) to help making it work?
So, as you may be aware, iOS is a bit of a pain. To make libsodium correctly load and be consumed by NSec, here's what you need in the iOS project.
You need a built libsodium.a
for iOS. This could be avoided if the libsodium nuget shipped an iOS build, which would be just about doable I think with a GitHub macOS build runner.
Add:
<NativeReference Include="Platforms/iOS/libsodium.a" Kind="Static" ForceLoad="True" />
in the project file (probably in an '$(TargetFramework)'=='net7.0-ios'
) conditional.
The iOS build will statically link all the libsodium symbols directly into the generated binary, but that means there is no longer in a "libsodium" library to DllImport
, so we must tell it, using NativeLibrary.SetDllImportResolver()
:
// As early in your app as possible.
NativeLibrary.SetDllImportResolver(typeof(NSec.Cryptography.Ed25519).Assembly, ResolveLibsodium);
private static IntPtr ResolveLibsodium(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
{
if (libraryName == "libsodium")
{
return NativeLibrary.GetMainProgramHandle();
}
// fall back to the system resolver.
return IntPtr.Zero;
}
This is not necessary if the NSec library uses __Internal
rather than libsodium
for its DllImport
attributes (__Internal
is a special value that the runtime understands as "this program"), but obviously that only works on iOS.
Due to point 3, there is now no compile-time connection between the libsodium symbols consumed by the NSec library and the symbols themselves. So, the iOS compiler strips them out, removing all those libsodium functions.
To get around that, we currently duplicate the Interop
folder into our app, and change the Interop.Libraries.Libsodium
constant to __Internal
. These Interop functions are not used, but "trick" the compiler into preserving the symbols.
My instinct tells me that there may be a way to communicate this list of "preserve these symbols please" to the iOS compiler, but I haven't found a better way yet other than duplicating the code as we currently do.
It may be that if the NSec library did similar and included __Internal
variants of all it's interop methods that those would propagate and preserve the symbols, but I'm not sure, and that's really janky.
I've created a branch that changes the Interop.Libraries.Libsodium
constant to __Internal
on iOS: https://github.com/ektrah/nsec/compare/master...ios. Here is the NuGet package: artifact.zip. Could you check if that helps with 3. and 4.?
Could MSBuild .props and .targets in a package help making 2. more convenient?
Regarding 1., libsodium builds pre-compiled binaries for all Apple targets, but seems not to have included them in the NuGet package yet.
Don't props and targets in a package only apply to the directly-referencing package? What happens if it's referenced indirectly (as we do)?
If libsodium could build iOS and Android binaries into its nuget package, that would be superb, because we then don't need to maintain their own. I hadn't seen there were apple-target binaries available.
The linked page talks about buildTransitive
(NuGet 5.0+) for assets that flow transitively. I've never tried that yet though.
There has been some great discussion in https://github.com/jedisct1/libsodium/discussions/1235 about MacCatalyst support that also helps with iOS support (PR: https://github.com/jedisct1/libsodium/pull/1238). I think there are still a few last pieces missing, but not much. I don't know about Android.
@enclave-alistair Any feedback on the ios
branch?
libsodium
1.0.19 was released, and the current NSec.Cryptography
is locked to < 1.0.19
@davhdavh There's a preview release that supports 1.0.19. Even if there wasn't, it's important to remember that 1.0.19 was only released recently and people are busy and work on other things.
An updated NuGet package including the commit for "unmanaged function pointers" has been released.
Hi @ektrah, can I inquire as to your plans for the next nuget package release? We're currently maintaining a forked build so we can get your commit for "unmanaged function pointers" (https://github.com/ektrah/nsec/commit/114231a21aa75c5c90ea8e95da2777eeadfffe78), needed for iOS support, as a package.
I know iOS isn't on your official supported list, but we're using NSec quite successfully with a few build/loader tweaks in the iOS app, would be nice to switch over to the regular NSec package.