All Projects → alexruperez → Securepropertystorage

alexruperez / Securepropertystorage

Licence: mit
Helps you define secure storages for your properties using Swift property wrappers.

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Securepropertystorage

Persistencekit
Store and retrieve Codable objects to various persistence layers, in a couple lines of code!
Stars: ✭ 121 (-68.07%)
Mutual labels:  userdefaults, keychain
Prephirences
Prephirences is a Swift library that provides useful protocols and convenience methods to manage application preferences, configurations and app-state. UserDefaults
Stars: ✭ 548 (+44.59%)
Mutual labels:  userdefaults, keychain
swift-standard-clients
Client declarations and live implementations for standard iOS managers
Stars: ✭ 28 (-92.61%)
Mutual labels:  keychain, userdefaults
GenericLocalPersistence
GenericLocalPersistence is a clean and easy-to-use code that is useful for integrating local storage like UserDefaults, PList, Keychain.
Stars: ✭ 17 (-95.51%)
Mutual labels:  keychain, userdefaults
Uickeychainstore
UICKeyChainStore is a simple wrapper for Keychain on iOS, watchOS, tvOS and macOS. Makes using Keychain APIs as easy as NSUserDefaults.
Stars: ✭ 3,029 (+699.21%)
Mutual labels:  keychain
LAPSforMac
Local Administrator Password Solution for Mac
Stars: ✭ 29 (-92.35%)
Mutual labels:  keychain
MSession
A simple and sophisticated session and authentication solution written in Swift
Stars: ✭ 26 (-93.14%)
Mutual labels:  keychain
alks-cli
CLI for working with the ALKS service.
Stars: ✭ 40 (-89.45%)
Mutual labels:  keychain
Simplekeychain
A Keychain helper for iOS to make it very simple to store/obtain values from iOS Keychain
Stars: ✭ 360 (-5.01%)
Mutual labels:  keychain
Go Keychain
Golang keychain package for iOS and macOS
Stars: ✭ 323 (-14.78%)
Mutual labels:  keychain
pinentry-touchid
Custom GPG pinentry program for macOS that allows using Touch ID for fetching the password from the macOS keychain.
Stars: ✭ 152 (-59.89%)
Mutual labels:  keychain
WaxSealCore
Simple, expressive yet comprehensive keychain wrapper in Objective-C.
Stars: ✭ 33 (-91.29%)
Mutual labels:  keychain
Csv2keychain
Small tool for adding exported credentials from Chrome to macOS keychain
Stars: ✭ 295 (-22.16%)
Mutual labels:  keychain
osx-callhistory-decryptor
macOS (incl big sur) call history decryptor/converter to CSV format.
Stars: ✭ 19 (-94.99%)
Mutual labels:  keychain
Chezmoi
Manage your dotfiles across multiple diverse machines, securely.
Stars: ✭ 5,590 (+1374.93%)
Mutual labels:  keychain
AC-iOS-Codeable-and-UserDefaults
No description or website provided.
Stars: ✭ 16 (-95.78%)
Mutual labels:  userdefaults
Gokey
A simple vaultless password manager in Go
Stars: ✭ 305 (-19.53%)
Mutual labels:  keychain
KeychainWrapper
A lightweight, pure-Swift library for the iOS keychain.
Stars: ✭ 51 (-86.54%)
Mutual labels:  keychain
UserDefaultsEVO
Using UserDefaults in a swift way
Stars: ✭ 20 (-94.72%)
Mutual labels:  userdefaults
Csvkeychain
Import/export between Apple Keychain.app and plain CSV file.
Stars: ✭ 281 (-25.86%)
Mutual labels:  keychain

🔐 Secure Property Storage

Helps you define secure storages for your properties using Swift property wrappers.

Twitter Swift License Swift Package Manager Carthage Bitrise Quality Maintainability Coverage Documentation

🌟 Features

All keys are hashed using SHA512 and all values are encrypted using AES-GCM to keep user information safe, automagically. Symmetric key and nonce, are stored in Keychain in a totally secure way.

🐒 Basic usage

@UserDefault

This property wrapper will store your property in UserDefaults using StoreKey (any String but i recommend you a String typed enum). Optionally, you can assign a default value to the property that will be secure stored at initialization.

@UserDefault(<#StoreKey#>)
var yourProperty: YourType? = yourDefaultValueIfNeeded

UserDefaultsStorage is also available, a subclass of UserDefaults with all the security provided by this library, where you can customize suite name.

@Keychain

This property wrapper will store your property in Keychain using StoreKey.

@Keychain(<#StoreKey#>)
var yourProperty: YourType? = yourDefaultValueIfNeeded

As UserDefaultsStorage, KeychainStorage is also available, where you can customize access, group and synchronize it with iCloud.

@Singleton

This property wrapper will store your property in a memory singleton, every property with the same wrapper and key can access or modify the value from wherever it is.

@Singleton(<#StoreKey#>)
var yourProperty: YourType? = yourDefaultValueIfNeeded

As KeychainStorage, SingletonStorage is also available.

@Inject

This property wrapper is similar to @Singleton but, together with @Register, will inject your dependencies. More details in Dependency Injection usage guide.

@Inject
var yourDependency: YourProtocol?

As SingletonStorage, InjectStorage is also available.

@Store

This is a custom wrapper, you can define your own Storage protocol implementation.

@Store(<#YourStorage#>, <#StoreKey#>)
var yourProperty: YourType? = yourDefaultValueIfNeeded

As InjectStorage, DelegatedStorage is also available with all the magic of this library.

🧙‍♂️ Codable usage

If your property conforms Codable protocol, just add Codable keyword as prefix of your property wrapper.

  • @CodableUserDefault
  • @CodableKeychain
  • @CodableSingleton
  • @CodableStore

🥡 Unwrapped usage

To avoid continually unwrapping your property, just add Unwrapped keyword as prefix of your property wrapper, assign a default value (mandatory except for @UnwrappedInject), and it will return stored value or default value, but your property will always be there for you.

  • @UnwrappedUserDefault
  • @UnwrappedKeychain
  • @UnwrappedSingleton
  • @UnwrappedInject
  • @UnwrappedStore

🥡 + 🧙‍♂️ Combo usage

You can also combine previous cases in case you need it, unwrapped first please.

  • @UnwrappedCodableUserDefault
  • @UnwrappedCodableKeychain
  • @UnwrappedCodableSingleton
  • @UnwrappedCodableStore

💉 Dependency Injection usage

@Register (click to expand)

This property wrapper will register the implementations of your dependencies. Register them wherever you want before inject it, but be sure to do it only once (except if you use qualifiers), for example, in an Injector class. You can register through a protocol or directly using your class implementation.

@Register
var yourDependency: YourProtocol = YourImplementation()

@Register
var yourDependency = YourImplementation()

You can also define a closure that builds your dependency. Just remember cast your dependency if you are going to inject it through a protocol.

@Register
var yourDependency = {
    YourImplementation() as YourProtocol
}

@Register
var yourDependency = {
    YourImplementation()
}
@Inject and @UnwrappedInject (click to expand)

These property wrappers injects your dependencies @Register implementations.

@Inject
var yourDependency: YourProtocol?

@Inject
var yourDependency: YourImplementation?

@UnwrappedInject
var yourUnwrappedDependency: YourProtocol

@UnwrappedInject
var yourUnwrappedDependency: YourImplementation

Scope

Because these property wrappers works similarly to @Singleton, the default scope is .singleton, but if you use builder closures on @Register, you can modify them to inject a single instance.

@Inject(.instance)
var yourDependency: YourProtocol?

@UnwrappedInject(.instance)
var yourUnwrappedDependency: YourProtocol
@InjectWith and @UnwrappedInjectWith (click to expand)

Your dependency may need parameters when injecting, you can pass them with these property wrappers. Simply define a model with your dependency parameters and pass it. It will inject a new instance built with these parameters.

@Register
var yourDependency = { parameters in
    YourImplementation(parameters) as YourProtocol
}

@Inject(YourParameters())
var yourDependency: YourProtocol?

@UnwrappedInject(YourParameters())
var yourUnwrappedDependency: YourProtocol
Qualifiers (click to expand)

You can use qualifiers to provide various implementations of a particular dependency. A qualifier is just a @objc protocol that you apply to a class.

For example, you could declare Dog and Cat qualifier protocols and apply it to another class that conforms Animal protocol. To declare this qualifier, use the following code:

protocol Animal {
  func sound()
}

@objc protocol Dog {}

@objc protocol Cat {}

You can then define multiple classes that conforms Animal protocol and uses this qualifiers:

class DogImplementation: Animal, Dog {
    func sound() { print("Woof!") }
}

class CatImplementation: Animal, Cat {
    func sound() { print("Meow!") }
}

Both implementations of the class can now be @Register:

@Register
var registerDog: Animal = DogImplementation()

@Register
var registerCat: Animal = CatImplementation()

To inject one or the other implementation, simply add the qualifier(s) to your @Inject:

@UnwrappedInject(Dog.self)
var dog: Animal

@UnwrappedInject(Cat.self)
var cat: Animal

dog.sound() // prints Woof!
cat.sound() // prints Meow!
Testing (click to expand)

One of the advantages of dependency injection is that the code can be easily testable with mock implementation. That is why there is a Mock qualifier that has priority over all, so you can have your dependencies defined in the app and create your mock in the test target simply by adding this qualifier.

// App target

class YourImplementation: YourProtocol {}

@Register
var yourDependency: YourProtocol = YourImplementation()

@Inject
var yourDependency: YourProtocol?
// Test target

class YourMock: YourProtocol, Mock {}

@Register
var yourDependency: YourProtocol = YourMock()

👀 Examples

Talk is cheap. Show me the code.

    // Securely stored in UserDefaults.
    @UserDefault("username")
    var username: String?

    // Securely stored in Keychain.
    @Keychain("password")
    var password: String?

    // Securely stored in a Singleton storage.
    @Singleton("sessionToken")
    var sessionToken: String?

    // Securely stored in a Singleton storage.
    // Always has a value, the stored or the default.
    @UnwrappedSingleton("refreshToken")
    var refreshToken: String = "B0610306-A33F"

    struct User: Codable {
        let username: String
        let password: String?
        let sessionToken: String?
    }

    // Codable model securely stored in UserDefaults.
    @CodableUserDefault("user")
    var user: User?

🛠 Compatibility

  • macOS 10.15+
  • iOS 13.0+
  • iPadOS 13.0+
  • tvOS 13.0+
  • watchOS 6.0+

⚙️ Installation

You can use the Swift Package Manager by declaring SecurePropertyStorage as a dependency in your Package.swift file:

.package(url: "https://github.com/alexruperez/SecurePropertyStorage", from: "0.3.0")

By default, all property wrappers are installed and you can import them, but if you want, you can install only some of them:

  • UserDefault: @*UserDefault property wrappers.
  • Keychain: @*Keychain property wrappers.
  • Singleton: @*Singleton property wrappers.
  • Storage: @*Store property wrappers.
  • Inject: @*Inject property wrappers.

For more information, see the Swift Package Manager documentation.

Or you can use Carthage:

github "alexruperez/SecurePropertyStorage"

🍻 Etc.

  • Featured in Dave Verwer's iOS Dev Weekly - Issue 450, thanks Dave!
  • Contributions are very welcome.
  • Attribution is appreciated (let's spread the word!), but not mandatory.

👨‍💻 Author

Alex Rupérez – @alexruperez[email protected]

👮‍♂️ License

SecurePropertyStorage is available under the MIT license. See the LICENSE file for more info.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].