[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-6743":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":22,"hasPages":22,"topics":24,"createdAt":10,"pushedAt":10,"updatedAt":28,"readmeContent":29,"aiSummary":30,"trendingCount":16,"starSnapshotCount":16,"syncStatus":31,"lastSyncTime":32,"discoverSource":33},6743,"KeychainAccess","kishikawakatsumi\u002FKeychainAccess","kishikawakatsumi","Simple Swift wrapper for Keychain that works on iOS, watchOS, tvOS and macOS.","",null,"Swift",8248,840,126,48,0,3,7,1,39.77,"MIT License",false,"master",[25,26,27],"keychain","security","touch-id","2026-06-12 02:01:29","# KeychainAccess\n\n[![Build Status](https:\u002F\u002Ftravis-ci.com\u002Fkishikawakatsumi\u002FKeychainAccess.svg?branch=master)](https:\u002F\u002Ftravis-ci.com\u002Fkishikawakatsumi\u002FKeychainAccess)\n[![Carthage compatible](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FCarthage-compatible-4BC51D.svg?style=flat)](https:\u002F\u002Fgithub.com\u002FCarthage\u002FCarthage)\n[![SPM supported](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FSPM-supported-DE5C43.svg?style=flat)](https:\u002F\u002Fswift.org\u002Fpackage-manager)\n[![Version](https:\u002F\u002Fimg.shields.io\u002Fcocoapods\u002Fv\u002FKeychainAccess.svg)](http:\u002F\u002Fcocoadocs.org\u002Fdocsets\u002FKeychainAccess)\n[![Platform](https:\u002F\u002Fimg.shields.io\u002Fcocoapods\u002Fp\u002FKeychainAccess.svg)](http:\u002F\u002Fcocoadocs.org\u002Fdocsets\u002FKeychainAccess)\n\nKeychainAccess is a simple Swift wrapper for Keychain that works on iOS and macOS. Makes using Keychain APIs extremely easy and much more palatable to use in Swift.\n\n\u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fkishikawakatsumi\u002FKeychainAccess\u002Fassets\u002F40610\u002F4de4aae1-6fc1-4477-af6d-afbe6d164da0\" width=\"320px\" \u002F> \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fkishikawakatsumi\u002FKeychainAccess\u002Fassets\u002F40610\u002F2980ea84-862b-4067-b9b7-90de629171b9\" width=\"320px\" \u002F>\n\u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fkishikawakatsumi\u002FKeychainAccess\u002Fassets\u002F40610\u002F3299347d-eb1b-446c-921c-778fa493f818\" width=\"320px\" \u002F>\n\n## :bulb: Features\n\n- Simple interface\n- Support access group\n- [Support accessibility](#accessibility)\n- [Support iCloud sharing](#icloud_sharing)\n- **[Support TouchID and Keychain integration (iOS 8+)](#touch_id_integration)**\n- **[Support Shared Web Credentials (iOS 8+)](#shared_web_credentials)**\n- [Works on both iOS & macOS](#requirements)\n- [watchOS and tvOS are supported](#requirements)\n- **[Mac Catalyst is supported](#requirements)**\n- **[Swift 3, 4 and 5 compatible](#requirements)**\n\n## :book: Usage\n\n##### :eyes: See also:\n\n- [:link: iOS Example Project](https:\u002F\u002Fgithub.com\u002Fkishikawakatsumi\u002FKeychainAccess\u002Ftree\u002Fmaster\u002FExamples\u002FExample-iOS)\n\n### :key: Basics\n\n#### Saving Application Password\n\n```swift\nlet keychain = Keychain(service: \"com.example.github-token\")\nkeychain[\"kishikawakatsumi\"] = \"01234567-89ab-cdef-0123-456789abcdef\"\n```\n\n#### Saving Internet Password\n\n```swift\nlet keychain = Keychain(server: \"https:\u002F\u002Fgithub.com\", protocolType: .https)\nkeychain[\"kishikawakatsumi\"] = \"01234567-89ab-cdef-0123-456789abcdef\"\n```\n\n### :key: Instantiation\n\n#### Create Keychain for Application Password\n\n```swift\nlet keychain = Keychain(service: \"com.example.github-token\")\n```\n\n```swift\nlet keychain = Keychain(service: \"com.example.github-token\", accessGroup: \"12ABCD3E4F.shared\")\n```\n\n#### Create Keychain for Internet Password\n\n```swift\nlet keychain = Keychain(server: \"https:\u002F\u002Fgithub.com\", protocolType: .https)\n```\n\n```swift\nlet keychain = Keychain(server: \"https:\u002F\u002Fgithub.com\", protocolType: .https, authenticationType: .htmlForm)\n```\n\n### :key: Adding an item\n\n#### subscripting\n\n##### for String\n\n```swift\nkeychain[\"kishikawakatsumi\"] = \"01234567-89ab-cdef-0123-456789abcdef\"\n```\n\n```swift\nkeychain[string: \"kishikawakatsumi\"] = \"01234567-89ab-cdef-0123-456789abcdef\"\n```\n\n##### for NSData\n\n```swift\nkeychain[data: \"secret\"] = NSData(contentsOfFile: \"secret.bin\")\n```\n\n#### set method\n\n```swift\nkeychain.set(\"01234567-89ab-cdef-0123-456789abcdef\", key: \"kishikawakatsumi\")\n```\n\n#### error handling\n\n```swift\ndo {\n    try keychain.set(\"01234567-89ab-cdef-0123-456789abcdef\", key: \"kishikawakatsumi\")\n}\ncatch let error {\n    print(error)\n}\n```\n\n### :key: Obtaining an item\n\n#### subscripting\n\n##### for String (If the value is NSData, attempt to convert to String)\n\n```swift\nlet token = keychain[\"kishikawakatsumi\"]\n```\n\n```swift\nlet token = keychain[string: \"kishikawakatsumi\"]\n```\n\n##### for NSData\n\n```swift\nlet secretData = keychain[data: \"secret\"]\n```\n\n#### get methods\n\n##### as String\n\n```swift\nlet token = try? keychain.get(\"kishikawakatsumi\")\n```\n\n```swift\nlet token = try? keychain.getString(\"kishikawakatsumi\")\n```\n\n##### as NSData\n\n```swift\nlet data = try? keychain.getData(\"kishikawakatsumi\")\n```\n\n### :key: Removing an item\n\n#### subscripting\n\n```swift\nkeychain[\"kishikawakatsumi\"] = nil\n```\n\n#### remove method\n\n```swift\ndo {\n    try keychain.remove(\"kishikawakatsumi\")\n} catch let error {\n    print(\"error: \\(error)\")\n}\n```\n\n### :key: Set Label and Comment\n\n```swift\nlet keychain = Keychain(server: \"https:\u002F\u002Fgithub.com\", protocolType: .https)\ndo {\n    try keychain\n        .label(\"github.com (kishikawakatsumi)\")\n        .comment(\"github access token\")\n        .set(\"01234567-89ab-cdef-0123-456789abcdef\", key: \"kishikawakatsumi\")\n} catch let error {\n    print(\"error: \\(error)\")\n}\n```\n\n### :key: Obtaining Other Attributes\n\n#### PersistentRef\n\n```swift\nlet keychain = Keychain()\nlet persistentRef = keychain[attributes: \"kishikawakatsumi\"]?.persistentRef\n...\n```\n\n#### Creation Date\n\n```swift\nlet keychain = Keychain()\nlet creationDate = keychain[attributes: \"kishikawakatsumi\"]?.creationDate\n...\n```\n\n#### All Attributes\n\n```swift\nlet keychain = Keychain()\ndo {\n    let attributes = try keychain.get(\"kishikawakatsumi\") { $0 }\n    print(attributes?.comment)\n    print(attributes?.label)\n    print(attributes?.creator)\n    ...\n} catch let error {\n    print(\"error: \\(error)\")\n}\n```\n\n##### subscripting\n\n```swift\nlet keychain = Keychain()\nif let attributes = keychain[attributes: \"kishikawakatsumi\"] {\n    print(attributes.comment)\n    print(attributes.label)\n    print(attributes.creator)\n}\n```\n\n### :key: Configuration (Accessibility, Sharing, iCloud Sync)\n\n**Provides fluent interfaces**\n\n```swift\nlet keychain = Keychain(service: \"com.example.github-token\")\n    .label(\"github.com (kishikawakatsumi)\")\n    .synchronizable(true)\n    .accessibility(.afterFirstUnlock)\n```\n\n#### \u003Ca name=\"accessibility\"> Accessibility\n\n##### Default accessibility matches background application (=kSecAttrAccessibleAfterFirstUnlock)\n\n```swift\nlet keychain = Keychain(service: \"com.example.github-token\")\n```\n\n##### For background application\n\n###### Creating instance\n\n```swift\nlet keychain = Keychain(service: \"com.example.github-token\")\n    .accessibility(.afterFirstUnlock)\n\nkeychain[\"kishikawakatsumi\"] = \"01234567-89ab-cdef-0123-456789abcdef\"\n```\n\n###### One-shot\n\n```swift\nlet keychain = Keychain(service: \"com.example.github-token\")\n\ndo {\n    try keychain\n        .accessibility(.afterFirstUnlock)\n        .set(\"01234567-89ab-cdef-0123-456789abcdef\", key: \"kishikawakatsumi\")\n} catch let error {\n    print(\"error: \\(error)\")\n}\n```\n\n##### For foreground application\n\n###### Creating instance\n\n```swift\nlet keychain = Keychain(service: \"com.example.github-token\")\n    .accessibility(.whenUnlocked)\n\nkeychain[\"kishikawakatsumi\"] = \"01234567-89ab-cdef-0123-456789abcdef\"\n```\n\n###### One-shot\n\n```swift\nlet keychain = Keychain(service: \"com.example.github-token\")\n\ndo {\n    try keychain\n        .accessibility(.whenUnlocked)\n        .set(\"01234567-89ab-cdef-0123-456789abcdef\", key: \"kishikawakatsumi\")\n} catch let error {\n    print(\"error: \\(error)\")\n}\n```\n\n#### :couple: Sharing Keychain items\n\n```swift\nlet keychain = Keychain(service: \"com.example.github-token\", accessGroup: \"12ABCD3E4F.shared\")\n```\n\n#### \u003Ca name=\"icloud_sharing\"> :arrows_counterclockwise: Synchronizing Keychain items with iCloud\n\n###### Creating instance\n\n```swift\nlet keychain = Keychain(service: \"com.example.github-token\")\n    .synchronizable(true)\n\nkeychain[\"kishikawakatsumi\"] = \"01234567-89ab-cdef-0123-456789abcdef\"\n```\n\n###### One-shot\n\n```swift\nlet keychain = Keychain(service: \"com.example.github-token\")\n\ndo {\n    try keychain\n        .synchronizable(true)\n        .set(\"01234567-89ab-cdef-0123-456789abcdef\", key: \"kishikawakatsumi\")\n} catch let error {\n    print(\"error: \\(error)\")\n}\n```\n\n### \u003Ca name=\"touch_id_integration\"> :cyclone: Touch ID (Face ID) integration\n\n**Any Operation that require authentication must be run in the background thread.**  \n**If you run in the main thread, UI thread will lock for the system to try to display the authentication dialog.**\n\n**To use Face ID, add `NSFaceIDUsageDescription` key to your `Info.plist`**\n\n#### :closed_lock_with_key: Adding a Touch ID (Face ID) protected item\n\nIf you want to store the Touch ID protected Keychain item, specify `accessibility` and `authenticationPolicy` attributes.\n\n```swift\nlet keychain = Keychain(service: \"com.example.github-token\")\n\nDispatchQueue.global().async {\n    do {\n        \u002F\u002F Should be the secret invalidated when passcode is removed? If not then use `.WhenUnlocked`\n        try keychain\n            .accessibility(.whenPasscodeSetThisDeviceOnly, authenticationPolicy: [.biometryAny])\n            .set(\"01234567-89ab-cdef-0123-456789abcdef\", key: \"kishikawakatsumi\")\n    } catch let error {\n        \u002F\u002F Error handling if needed...\n    }\n}\n```\n\n#### :closed_lock_with_key: Updating a Touch ID (Face ID) protected item\n\nThe same way as when adding.\n\n**Do not run in the main thread if there is a possibility that the item you are trying to add already exists, and protected.**\n**Because updating protected items requires authentication.**\n\nAdditionally, you want to show custom authentication prompt message when updating, specify an `authenticationPrompt` attribute.\nIf the item not protected, the `authenticationPrompt` parameter just be ignored.\n\n```swift\nlet keychain = Keychain(service: \"com.example.github-token\")\n\nDispatchQueue.global().async {\n    do {\n        \u002F\u002F Should be the secret invalidated when passcode is removed? If not then use `.WhenUnlocked`\n        try keychain\n            .accessibility(.whenPasscodeSetThisDeviceOnly, authenticationPolicy: [.biometryAny])\n            .authenticationPrompt(\"Authenticate to update your access token\")\n            .set(\"01234567-89ab-cdef-0123-456789abcdef\", key: \"kishikawakatsumi\")\n    } catch let error {\n        \u002F\u002F Error handling if needed...\n    }\n}\n```\n\n#### :closed_lock_with_key: Obtaining a Touch ID (Face ID) protected item\n\nThe same way as when you get a normal item. It will be displayed automatically Touch ID or passcode authentication If the item you try to get is protected.  \nIf you want to show custom authentication prompt message, specify an `authenticationPrompt` attribute.\nIf the item not protected, the `authenticationPrompt` parameter just be ignored.\n\n```swift\nlet keychain = Keychain(service: \"com.example.github-token\")\n\nDispatchQueue.global().async {\n    do {\n        let password = try keychain\n            .authenticationPrompt(\"Authenticate to login to server\")\n            .get(\"kishikawakatsumi\")\n\n        print(\"password: \\(password)\")\n    } catch let error {\n        \u002F\u002F Error handling if needed...\n    }\n}\n```\n\n#### :closed_lock_with_key: Removing a Touch ID (Face ID) protected item\n\nThe same way as when you remove a normal item.\nThere is no way to show Touch ID or passcode authentication when removing Keychain items.\n\n```swift\nlet keychain = Keychain(service: \"com.example.github-token\")\n\ndo {\n    try keychain.remove(\"kishikawakatsumi\")\n} catch let error {\n    \u002F\u002F Error handling if needed...\n}\n```\n\n### \u003Ca name=\"shared_web_credentials\"> :key: Shared Web Credentials\n\n> Shared web credentials is a programming interface that enables native iOS apps to share credentials with their website counterparts. For example, a user may log in to a website in Safari, entering a user name and password, and save those credentials using the iCloud Keychain. Later, the user may run a native app from the same developer, and instead of the app requiring the user to reenter a user name and password, shared web credentials gives it access to the credentials that were entered earlier in Safari. The user can also create new accounts, update passwords, or delete her account from within the app. These changes are then saved and used by Safari.  \n> \u003Chttps:\u002F\u002Fdeveloper.apple.com\u002Flibrary\u002Fios\u002Fdocumentation\u002FSecurity\u002FReference\u002FSharedWebCredentialsRef\u002F>\n\n```swift\nlet keychain = Keychain(server: \"https:\u002F\u002Fwww.kishikawakatsumi.com\", protocolType: .HTTPS)\n\nlet username = \"kishikawakatsumi@mac.com\"\n\n\u002F\u002F First, check the credential in the app's Keychain\nif let password = try? keychain.get(username) {\n    \u002F\u002F If found password in the Keychain,\n    \u002F\u002F then log into the server\n} else {\n    \u002F\u002F If not found password in the Keychain,\n    \u002F\u002F try to read from Shared Web Credentials\n    keychain.getSharedPassword(username) { (password, error) -> () in\n        if password != nil {\n            \u002F\u002F If found password in the Shared Web Credentials,\n            \u002F\u002F then log into the server\n            \u002F\u002F and save the password to the Keychain\n\n            keychain[username] = password\n        } else {\n            \u002F\u002F If not found password either in the Keychain also Shared Web Credentials,\n            \u002F\u002F prompt for username and password\n\n            \u002F\u002F Log into server\n\n            \u002F\u002F If the login is successful,\n            \u002F\u002F save the credentials to both the Keychain and the Shared Web Credentials.\n\n            keychain[username] = inputPassword\n            keychain.setSharedPassword(inputPassword, account: username)\n        }\n    }\n}\n```\n\n#### Request all associated domain's credentials\n\n```swift\nKeychain.requestSharedWebCredential { (credentials, error) -> () in\n\n}\n```\n\n#### Generate strong random password\n\nGenerate strong random password that is in the same format used by Safari autofill (xxx-xxx-xxx-xxx).\n\n```swift\nlet password = Keychain.generatePassword() \u002F\u002F => Nhu-GKm-s3n-pMx\n```\n\n#### How to set up Shared Web Credentials\n\n> 1. Add a com.apple.developer.associated-domains entitlement to your app. This entitlement must include all the domains with which you want to share credentials.\n>\n> 2. Add an apple-app-site-association file to your website. This file must include application identifiers for all the apps with which the site wants to share credentials, and it must be properly signed.\n>\n> 3. When the app is installed, the system downloads and verifies the site association file for each of its associated domains. If the verification is successful, the app is associated with the domain.\n\n**More details:**  \n\u003Chttps:\u002F\u002Fdeveloper.apple.com\u002Flibrary\u002Fios\u002Fdocumentation\u002FSecurity\u002FReference\u002FSharedWebCredentialsRef\u002F>\n\n### :mag: Debugging\n\n#### Display all stored items if print keychain object\n\n```swift\nlet keychain = Keychain(server: \"https:\u002F\u002Fgithub.com\", protocolType: .https)\nprint(\"\\(keychain)\")\n```\n\n```\n=>\n[\n  [authenticationType: default, key: kishikawakatsumi, server: github.com, class: internetPassword, protocol: https]\n  [authenticationType: default, key: hirohamada, server: github.com, class: internetPassword, protocol: https]\n  [authenticationType: default, key: honeylemon, server: github.com, class: internetPassword, protocol: https]\n]\n```\n\n#### Obtaining all stored keys\n\n```swift\nlet keychain = Keychain(server: \"https:\u002F\u002Fgithub.com\", protocolType: .https)\n\nlet keys = keychain.allKeys()\nfor key in keys {\n  print(\"key: \\(key)\")\n}\n```\n\n```\n=>\nkey: kishikawakatsumi\nkey: hirohamada\nkey: honeylemon\n```\n\n#### Obtaining all stored items\n\n```swift\nlet keychain = Keychain(server: \"https:\u002F\u002Fgithub.com\", protocolType: .https)\n\nlet items = keychain.allItems()\nfor item in items {\n  print(\"item: \\(item)\")\n}\n```\n\n```\n=>\nitem: [authenticationType: Default, key: kishikawakatsumi, server: github.com, class: InternetPassword, protocol: https]\nitem: [authenticationType: Default, key: hirohamada, server: github.com, class: InternetPassword, protocol: https]\nitem: [authenticationType: Default, key: honeylemon, server: github.com, class: InternetPassword, protocol: https]\n```\n\n## Keychain sharing capability\n\nIf you encounter the error below, you need to add an `Keychain.entitlements`.\n\n```\nOSStatus error:[-34018] Internal error when a required entitlement isn't present, client has neither application-identifier nor keychain-access-groups entitlements.\n```\n\n\u003Cimg alt=\"Screen Shot 2019-10-27 at 8 08 50\" src=\"https:\u002F\u002Fuser-images.githubusercontent.com\u002F40610\u002F67627108-1a7f2f80-f891-11e9-97bc-7f7313cb63d1.png\" width=\"500\">\n\n\u003Cimg src=\"https:\u002F\u002Fuser-images.githubusercontent.com\u002F40610\u002F67627072-333b1580-f890-11e9-9feb-bf507abc2724.png\" width=\"500\" \u002F>\n\n## Requirements\n\n|            | OS                                                         | Swift              |\n| ---------- | ---------------------------------------------------------- | ------------------ |\n| **v1.1.x** | iOS 7+, macOS 10.9+                                        | 1.1                |\n| **v1.2.x** | iOS 7+, macOS 10.9+                                        | 1.2                |\n| **v2.0.x** | iOS 7+, macOS 10.9+, watchOS 2+                            | 2.0                |\n| **v2.1.x** | iOS 7+, macOS 10.9+, watchOS 2+                            | 2.0                |\n| **v2.2.x** | iOS 8+, macOS 10.9+, watchOS 2+, tvOS 9+                   | 2.0, 2.1           |\n| **v2.3.x** | iOS 8+, macOS 10.9+, watchOS 2+, tvOS 9+                   | 2.0, 2.1, 2.2      |\n| **v2.4.x** | iOS 8+, macOS 10.9+, watchOS 2+, tvOS 9+                   | 2.2, 2.3           |\n| **v3.0.x** | iOS 8+, macOS 10.9+, watchOS 2+, tvOS 9+                   | 3.x                |\n| **v3.1.x** | iOS 8+, macOS 10.9+, watchOS 2+, tvOS 9+                   | 4.0, 4.1, 4.2      |\n| **v3.2.x** | iOS 8+, macOS 10.9+, watchOS 2+, tvOS 9+                   | 4.0, 4.1, 4.2, 5.0 |\n| **v4.0.x** | iOS 8+, macOS 10.9+, watchOS 2+, tvOS 9+                   | 4.0, 4.1, 4.2, 5.1 |\n| **v4.1.x** | iOS 8+, macOS 10.9+, watchOS 3+, tvOS 9+, Mac Catalyst 13+ | 4.0, 4.1, 4.2, 5.1 |\n\n## Installation\n\n### CocoaPods\n\nKeychainAccess is available through [CocoaPods](http:\u002F\u002Fcocoapods.org). To install\nit, simply add the following lines to your Podfile:\n\n```ruby\nuse_frameworks!\npod 'KeychainAccess'\n```\n\n### Carthage\n\nKeychainAccess is available through [Carthage](https:\u002F\u002Fgithub.com\u002FCarthage\u002FCarthage). To install\nit, simply add the following line to your Cartfile:\n\n`github \"kishikawakatsumi\u002FKeychainAccess\"`\n\n### Swift Package Manager\n\nKeychainAccess is also available through [Swift Package Manager](https:\u002F\u002Fgithub.com\u002Fapple\u002Fswift-package-manager\u002F).\n\n#### Xcode\n\nSelect `File > Add Packages... > Add Package Dependency...`,\n\n\u003Cimg src=\"https:\u002F\u002Fuser-images.githubusercontent.com\u002F40610\u002F67627000-2833b580-f88f-11e9-89ef-18819b1a6c67.png\" width=\"800px\" \u002F>\n\n#### CLI\n\nFirst, create `Package.swift` that its package declaration includes:\n\n```swift\n\u002F\u002F swift-tools-version:5.0\nimport PackageDescription\n\nlet package = Package(\n    name: \"MyLibrary\",\n    products: [\n        .library(name: \"MyLibrary\", targets: [\"MyLibrary\"]),\n    ],\n    dependencies: [\n        .package(url: \"https:\u002F\u002Fgithub.com\u002Fkishikawakatsumi\u002FKeychainAccess.git\", from: \"3.0.0\"),\n    ],\n    targets: [\n        .target(name: \"MyLibrary\", dependencies: [\"KeychainAccess\"]),\n    ]\n)\n```\n\nThen, type\n\n```shell\n$ swift build\n```\n\n### To manually add to your project\n\n1. Add `Lib\u002FKeychainAccess.xcodeproj` to your project\n2. Link `KeychainAccess.framework` with your target\n3. Add `Copy Files Build Phase` to include the framework to your application bundle\n\n_See [iOS Example Project](https:\u002F\u002Fgithub.com\u002Fkishikawakatsumi\u002FKeychainAccess\u002Ftree\u002Fmaster\u002FExamples\u002FExample-iOS) as reference._\n\n\u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fkishikawakatsumi\u002FKeychainAccess\u002Fassets\u002F40610\u002Fb7a46cfb-714d-47d5-84ea-6a80f640e03d\" width=\"800px\" \u002F>\n\n## Author\n\nkishikawa katsumi, kishikawakatsumi@mac.com\n\n## License\n\nKeychainAccess is available under the MIT license. See the LICENSE file for more info.\n","KeychainAccess 是一个简洁的 Swift 封装库，用于在 iOS、watchOS、tvOS 和 macOS 上操作 Keychain。它提供了简单易用的接口来访问和管理 Keychain 中的数据，支持访问组、iCloud 共享、TouchID 集成以及共享 Web 凭证等功能，并且兼容 Swift 3, 4 和 5。该库适用于需要安全存储敏感信息（如密码、令牌等）的应用场景，通过简化复杂的 Keychain API 调用，使开发者能够更方便地实现数据的安全存储与访问。",2,"2026-06-11 03:08:39","top_language"]