Home > Mobile >  How do I correctly store encryption keys on macOS so only my executable can access them?
How do I correctly store encryption keys on macOS so only my executable can access them?

Time:10-01

Introduction

Basically, how/where do I persist encryption keys my executable needs?

Let me explain how my executable looks like. It's basically a Swift script that is compiled using swift build --configuration=release --product=App.

Package.swift:

// swift-tools-version:5.3
import PackageDescription

let package = Package(
    name: "App",
    defaultLocalization: "en",
    platforms: [
        .macOS(.v10_15),
    ],
    products: [
        .executable(name: "App", targets: ["App"]),
    ],
    dependencies: [
        .package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.1"),
        .package(url: "https://github.com/apple/swift-crypto", from: "2.0.0")
    ],
    targets: [
        .target(name: "App", dependencies: [
            .product(name: "ArgumentParser", package: "swift-argument-parser"),
            .product(name: "Crypto", package: "swift-crypto"),
        ]),
    ]
)

Some Ideas

  • I know that Apple provides a Keychain on macOS to store keys. The problem is that my executable is not signed in any way, so it'd be difficult to enforce that only my executable can access the stored keys. (That's what I think at least, correct me if I'm wrong)

Git seems to somehow store user credentials in Keychain. How do they do it? Is their way even secure?

  • The next idea I had was to store the keys in the user's home directory, like .ssh. That seems insecure. As far as I know, any app running on the system could then read the keys, right?

  • Another way to achieve this would be to encrypt the key using a password and then make the user enter their password every time the key is needed. This is the least preferable option because it is inconvenient.

  • The last option I thought of would be to sign my executable somehow. Is there any way to sign my executable so it can have it's own guarded space in the Keychain? What I need is a process to sign my executable without requiring an Apple Developer Account or any other central authority.

Question

How can I securely store encryption keys so only my executable (edit: and the user) can access them?

CodePudding user response:

To protect your app from modification, codesign it. You can use a private key or use Apple's notarization service. This will ensure no one modifies your app or distributes an installer that tries to replace your app.

Keychain items your app creates can have access control lists, but even by default, the OS won't allow other apps to read your app's keychain items without being approved by the user. The user will receive a pop-up indicating the item the app is requesting.

So I believe your best bet is to sign your app, and store the data in Keychain. It should generally work as you want out of the box. But of course do a lot of testing. Generally these things fail-secure, so in most cases it won't leak any data to other apps. But you may get more pop-ups than you want the user to deal with if you make mistakes.

  • Related