Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Code signing requirements for native plugin

Discussion in 'macOS' started by guavaman, Feb 7, 2022.

  1. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,639
    Does anyone know what is the correct way to handle code signing for a MacOS native library (bundle) plugin that would be included in applications that may or may not be delivered on the Mac App Store? I've been unable to find any requirements or advice for libraries in any of the official Apple documentation, and nothing that references this scenario in Unity's documentation. Should a library plugin even be signed at all, or is Unity's application signing enough?

    Everything I've seen refers to code signing of the final application, not the individual libraries used in the application. I see that Unity signs the application it builds, but does this include signing of any included native plugins?

    Further, I see the Mac App Store has its own requirements for the signing identity.

    My concern is that I be able to distribute a single native library (bundle) that can be included in a project and be built into a final game and be able to be distributed through any means without signing identity conflicts or rejection from Mac App Store due to unsigned code or using the wrong signing identity.
     
  2. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,091
    I've used this in the past to sign builds and it's worked well (https://github.com/UNSH/Unity-Apple-Distribution-Workflow). It also signs any framework bundles that are part of the executable (.app file).

    The main issue you'll find is that Apple will reject the framework bundle because it's bundle ID has been used before in other apps and they need to be unique. The way to workaround this is just to append your company name onto the bundle ID inside the framework Info.plist.

    For example, if you use a bundle called 'FileBrowser' and it's Info.plist contains a bundle ID called 'com.plugins-r-us.filebrowser' you can just make that 'com.plugins-r-us.filebrowser.mycompany' and it'll upload ok.
     
  3. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,639
    Thanks for the reply. This is very helpful.

    So I assume that means Unity won't do this package-wide code signing (including the bundles) by itself without the use of additional tools.

    Oh wow. This sounds like a huge problem. Even appending the company name isn't sufficient if that company releases many games using the same plugin.

    Both of these issues are going to be a giant hassle for users if they have to go through special steps editing the .plist and downloading specific code signing tools in order to be able to publish an application containing this plugin (Rewired) to the Apple Store.

    Based on what you're saying, it sounds like there's no way I can publish an Asset Store package that includes a native Mac plugin that doesn't involve the user jumping through hoops because of the included bundle.
     
    Last edited: Feb 10, 2022
  4. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,091
    I started using that github system a long time ago when Unity didn’t have any native support for Mac signing so things may have changed a lot since then, maybe somebody else can provide more info on whether it also signs the additional frameworks too.

    If Unity now supports signing then you might just be able to change the plist bundle id in your framework to get around the problem of duplicate IDs. It’s worth trying it yourself and uploading an app to testflight to see how you get on. If that fails then I can at least confirm that the github system works for me and the company I work for has released commercial games using custom frameworks with it.

    As you said though, mac signing (for me at least) as always been a huge pain and involved manual workarounds for signing custom frameworks. I'm not sure if there is a way of providing frameworks to your users on the asset store without having to get them to modify the plist file to make it unique. I've attached a pic from another plugin dev (Prime31) that mentions the same problem.

    p.s. I've just realised you make Rewired (nice plugin btw) - we've used that before on Mac titles so let me check tomorrow and I can see what we did with it during signing.
     

    Attached Files:

    Last edited: Feb 10, 2022
  5. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,639
    Thanks for the information. It does seem like trial and error is the only way I'm really going to get concrete answers on some of this. The issue with the bundle identifier is pretty serious in my view. The image from the other asset is extremely helpful. Thanks for the information.

    As for Rewired, until now, Rewired has never included any native libraries on MacOS. All of its native input was handled through P/Invoking to the OSX API, so everything has always been exclusively C# on MacOS. This will be changing with coming native support for GameControllerFramework and an additional input source for MacOS. However, these bundle issues are very significant. If I can't find a way to make this more seamless, I may not release the update. Requiring the user to manually edit a .plist file in the library inside the built app is just plain bad user experience and guaranteed to lead to a bunch of additional support headaches.
     
    Last edited: Feb 11, 2022
  6. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,091
    Sorry, I may have confused you a little on the bundle id modification. You have to modify it -before- doing the build rather than having to do anything afterwards. From what I remember, your plugin had a 'welcome' popup in the editor after the first install. Perhaps as part of that welcome screen you could run some code that would read the plist file, append a random GUID to the end of the bundle ID and save it?

    There's a bit of example code here (https://forum.unity.com/threads/how-to-run-a-setup-method-when-a-package-is-imported-updated.656470/) that looks like it runs after a domain reload, you could use something like that to do it without having to require the user to press a button.
     
  7. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,639
    Oh, yes. I was thinking the .plist needed to be modified after, not before. I was also ruminating on ideas involving appending a GUID after build, though before would be easier. Rewired makes heavy use of editor code for all kinds of things related to setup and updating, so this would fit right in there. There are some potentially issues I've thought of with this approach:
    1. GUIDs are not guaranteed to be unique
    2. The GUID needs to be tied to the project so if the developer makes a new project, it doesn't get re-used.
    3. The GUID needs to be stored outside the Rewired folder so in case Rewired needs to be deleted and re-installed for whatever reason, they don't lose their GUID.
    4. The modified bundle would be replaced when updating Rewired because its part of the distribution, so this would have to change somehow. Probably some kind of MacOS native library installer that extracts the native library and changes the identifier. But there could also be the problem of the bundle files being locked from access by the Unity Editor because it's using them.
    For #1, at some point there could be a clash resulting in Apple rejecting the build. It would be very confusing. Perhaps I could build a web-based system to get a GUID or index from a server so it's guaranteed to be unique. This would also fail if the developer installed Rewired without internet or if the server was down at that time, so it would have to have all kinds of redundant checks at various points and warnings.

    Another idea would be to use the company name and product name they have set in the Unity Player settings. Or better, use the whole application bundle identifier, appending "rewired-macos" or something to it. They wouldn't be using the same identifier for multiple products. It would need to update whenever they change that though.
     
  8. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,702
    You could just ship a .dylib instead of a .bundle, that way you don't need to deal with plist files. FWIW we ship UnityPlayer.dylib ad-hoc signed (that means without any identity).
     
    bhall_unity and guavaman like this.
  9. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,639
    Oh! That's excellent! Thanks! I wasn't aware Unity allowed the use of .dylibs. When I originally wrote Rewired support for OSX (at the time it was going to be a native plugin as opposed to C# P/Invoke), Unity did not support dylibs, only bundles. This has actually been a problem for the optional SDL2 support as well, as I had to create a custom build of SDL2 to generate a bundle so it would work with Unity. If Unity supports dylibs now, that is excellent and would save me a ton of time for both SDL2 support and the new native library. I'll have to do some research and find out when this feature was added so I can set minimum Unity version required to use the library (because Rewired still supports as far back as Unity 4.3 even though only 2018.4+ can be downloaded from the Unity Asset Store).
     
    Last edited: Feb 11, 2022
  10. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,702
    Some older versions didn't support .dylibs, we added it not too long ago (I can't remember exactly when, it's been a few years). But even then, you could simply rename ".dylib" to ".bundle" without changing anything else and Unity will be "fooled" to treat it as a plugin. Burst actually did that for a long time before we started recognizing ".dylib" files.
     
  11. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,639
    It seems that distributing an ad-hoc signed a .bundle file leads to this warning when developers download Rewired:

    Screenshot 2024-01-16 at 10.37.11.png

    Did Unity experience this problem with UnityPlayer.dylib as well?
     
  12. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,702
    Yes, if you zip a Mac build, upload it somewhere and download it to another Mac, it will display the same dialog about "Game.app". This is Mac saying "we don't know who signed it". This happens when the file that is getting loaded has the "com.apple.quarantine" attribute, which gets added to whatever you download using a browser. It can be worked around locally by doing "xattr -r -d com.apple.quarantine /path/to/plugin.bundle" after downloading it.

    This is generally only an issue for the final game via a browser. If you download using Steam or AppStore, it will not result in that attribute getting applied to files.

    I can see how this can cause you issues as an asset developer... It should also not apply to files downloaded by Unity from the asset store, so I assume you're distributing this via your website? One way to work around this (and one we do for Unity Editor, as we distribute that via our website) is to make an installer instead of a zip file, as you will get that warning when running the installer, rather than when files from the zip file get loaded into an app.
     
  13. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,639
    Thank you for the extremely helpful info!

    I will have to ask the user who reported this how he downloaded Rewired. The vast majority of users would be getting it through the Unity Asset Store, but I do have downloads available on my site for registered users. The primary use case is for developers using versions of Unity that the Asset Store no longer supports (anything before 2019.4), as Rewired still supports Unity 4.3+. Also, the free trial can only be downloaded from my website.
     
    Last edited by a moderator: Jan 20, 2024
  14. greg-harding

    greg-harding

    Joined:
    Apr 11, 2013
    Posts:
    525
    Just chiming in to say that codesigning a mac app and its plugins when exported directly to an .app has been a pretty frustrating exercise for quite a few years. Apple change the rules/checks on the App Store now and again which means more checks and hacks are needed now and again to get things just right.

    We have a set of bash shell scripts that we run over an .app, finding nested .bundles and .dylibs, editing various Info.plists to append unique identifiers to avoid the bundle id clash with other apps shipping on the store, etc., and then finally codesigning the main .app.

    Anything that makes this process easier for any form of distribution (ad hoc or App Store) is very handy :)
     
    guavaman likes this.