Last active
April 9, 2017 02:49
-
-
Save oozoofrog/a3e321a6b0d0288045f3620818f8c6ae to your computer and use it in GitHub Desktop.
swift Security status
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import Security | |
public struct SwiftSecurity { | |
public enum SwiftSecurityError: Error { | |
case error(SecStatus) | |
} | |
public static func del<KEY: Hashable>(query: [KEY : Any]) throws { | |
guard let status = SecStatus.from(status: SecItemDelete(query as CFDictionary)), status != .Success else { | |
return | |
} | |
throw SwiftSecurityError.error(status) | |
} | |
public static func add<KEY: Hashable>(item: [KEY : Any]) throws { | |
var result: CFTypeRef? | |
defer { | |
print(result ?? "result none") | |
} | |
guard let status = SecStatus.from(status: SecItemAdd(item as CFDictionary, &result)), status != .Success else { | |
return | |
} | |
throw SwiftSecurityError.error(status) | |
} | |
public static func get<KEY: Hashable>(query: [KEY : Any]) throws -> CFTypeRef? { | |
var value: CFTypeRef? | |
let status = SecStatus.from(status: SecItemCopyMatching(query as CFDictionary, &value)) | |
if value == nil { | |
throw SwiftSecurityError.error(.ItemNotFound) | |
} else if let status = status, status != .Success { | |
throw SwiftSecurityError.error(status) | |
} | |
return value | |
} | |
} | |
public struct SecStatus: CustomStringConvertible, Hashable, Equatable { | |
public static func ==(lhs: SecStatus, rhs: SecStatus) -> Bool { | |
return lhs.hashValue == rhs.hashValue | |
} | |
public static let Success = SecStatus(status: errSecSuccess) | |
public static let Unimplemented = SecStatus(status: errSecUnimplemented) | |
public static let DskFull = SecStatus(status: errSecDskFull) | |
public static let IO = SecStatus(status: errSecIO) | |
public static let Param = SecStatus(status: errSecParam) | |
public static let WrPerm = SecStatus(status: errSecWrPerm) | |
public static let Allocate = SecStatus(status: errSecAllocate) | |
public static let UserCanceled = SecStatus(status: errSecUserCanceled) | |
public static let BadReq = SecStatus(status: errSecBadReq) | |
public static let InternalComponent = SecStatus(status: errSecInternalComponent) | |
public static let CoreFoundationUnknown = SecStatus(status: errSecCoreFoundationUnknown) | |
public static let NotAvailable = SecStatus(status: errSecNotAvailable) | |
public static let ReadOnly = SecStatus(status: errSecReadOnly) | |
public static let AuthFailed = SecStatus(status: errSecAuthFailed) | |
public static let NoSuchKeychain = SecStatus(status: errSecNoSuchKeychain) | |
public static let InvalidKeychain = SecStatus(status: errSecInvalidKeychain) | |
public static let DuplicateKeychain = SecStatus(status: errSecDuplicateKeychain) | |
public static let DuplicateCallback = SecStatus(status: errSecDuplicateCallback) | |
public static let InvalidCallback = SecStatus(status: errSecInvalidCallback) | |
public static let DuplicateItem = SecStatus(status: errSecDuplicateItem) | |
public static let ItemNotFound = SecStatus(status: errSecItemNotFound) | |
public static let BufferTooSmall = SecStatus(status: errSecBufferTooSmall) | |
public static let DataTooLarge = SecStatus(status: errSecDataTooLarge) | |
public static let NoSuchAttr = SecStatus(status: errSecNoSuchAttr) | |
public static let InvalidItemRef = SecStatus(status: errSecInvalidItemRef) | |
public static let InvalidSearchRef = SecStatus(status: errSecInvalidSearchRef) | |
public static let NoSuchClass = SecStatus(status: errSecNoSuchClass) | |
public static let NoDefaultKeychain = SecStatus(status: errSecNoDefaultKeychain) | |
public static let InteractionNotAllowed = SecStatus(status: errSecInteractionNotAllowed) | |
public static let ReadOnlyAttr = SecStatus(status: errSecReadOnlyAttr) | |
public static let WrongSecVersion = SecStatus(status: errSecWrongSecVersion) | |
public static let KeySizeNotAllowed = SecStatus(status: errSecKeySizeNotAllowed) | |
public static let NoStorageModule = SecStatus(status: errSecNoStorageModule) | |
public static let NoCertificateModule = SecStatus(status: errSecNoCertificateModule) | |
public static let NoPolicyModule = SecStatus(status: errSecNoPolicyModule) | |
public static let InteractionRequired = SecStatus(status: errSecInteractionRequired) | |
public static let DataNotAvailable = SecStatus(status: errSecDataNotAvailable) | |
public static let DataNotModifiable = SecStatus(status: errSecDataNotModifiable) | |
public static let CreateChainFailed = SecStatus(status: errSecCreateChainFailed) | |
public static let ACLNotSimple = SecStatus(status: errSecACLNotSimple) | |
public static let PolicyNotFound = SecStatus(status: errSecPolicyNotFound) | |
public static let InvalidTrustSetting = SecStatus(status: errSecInvalidTrustSetting) | |
public static let NoAccessForItem = SecStatus(status: errSecNoAccessForItem) | |
public static let InvalidOwnerEdit = SecStatus(status: errSecInvalidOwnerEdit) | |
public static let TrustNotAvailable = SecStatus(status: errSecTrustNotAvailable) | |
public static let UnsupportedFormat = SecStatus(status: errSecUnsupportedFormat) | |
public static let UnknownFormat = SecStatus(status: errSecUnknownFormat) | |
public static let KeyIsSensitive = SecStatus(status: errSecKeyIsSensitive) | |
public static let MultiplePrivKeys = SecStatus(status: errSecMultiplePrivKeys) | |
public static let PassphraseRequired = SecStatus(status: errSecPassphraseRequired) | |
public static let InvalidPasswordRef = SecStatus(status: errSecInvalidPasswordRef) | |
public static let InvalidTrustSettings = SecStatus(status: errSecInvalidTrustSettings) | |
public static let NoTrustSettings = SecStatus(status: errSecNoTrustSettings) | |
public static let Pkcs12VerifyFailure = SecStatus(status: errSecPkcs12VerifyFailure) | |
public static let Decode = SecStatus(status: errSecDecode) | |
public let status: OSStatus | |
public var message: String { return statusMessage(status: self.status) } | |
public var code: String { return statusCode(status: self.status) } | |
public var description: String { return "SecStatus: \(self.code), \(self.message)"} | |
private static let statuses: [SecStatus] = [Success, Unimplemented, DskFull, IO, Param, WrPerm, Allocate, UserCanceled, BadReq, InternalComponent, CoreFoundationUnknown, NotAvailable, ReadOnly, AuthFailed, NoSuchKeychain, InvalidKeychain, DuplicateKeychain, DuplicateCallback, InvalidCallback, DuplicateItem, ItemNotFound, BufferTooSmall, DataTooLarge, NoSuchAttr, InvalidItemRef, InvalidSearchRef, NoSuchClass, NoDefaultKeychain, InteractionNotAllowed, ReadOnlyAttr, WrongSecVersion, KeySizeNotAllowed, NoStorageModule, NoCertificateModule, NoPolicyModule, InteractionRequired, DataNotAvailable, DataNotModifiable, CreateChainFailed, ACLNotSimple, PolicyNotFound, InvalidTrustSetting, NoAccessForItem, InvalidOwnerEdit, TrustNotAvailable, UnsupportedFormat, UnknownFormat, KeyIsSensitive, MultiplePrivKeys, PassphraseRequired, InvalidPasswordRef, InvalidTrustSettings, NoTrustSettings, Pkcs12VerifyFailure, Decode] | |
private init() { fatalError("Don't use init") } | |
private init(status _status: OSStatus) { | |
status = _status | |
} | |
public var hashValue: Int { return Int(self.status) } | |
public static func from(status: OSStatus) -> SecStatus? { | |
return statuses.filter{ $0.status == status }.first | |
} | |
func statusCode(status: OSStatus) -> String { | |
switch status { | |
case errSecSuccess: return "errSecSuccess" | |
case errSecUnimplemented: return "errSecUnimplemented" | |
case errSecDskFull: return "errSecDskFull" | |
case errSecIO: return "errSecIO" | |
case errSecParam: return "errSecParam" | |
case errSecWrPerm: return "errSecWrPerm" | |
case errSecAllocate: return "errSecAllocate" | |
case errSecUserCanceled: return "errSecUserCanceled" | |
case errSecBadReq: return "errSecBadReq" | |
case errSecInternalComponent: return "errSecInternalComponent" | |
case errSecCoreFoundationUnknown: return "errSecCoreFoundationUnknown" | |
case errSecNotAvailable: return "errSecNotAvailable" | |
case errSecReadOnly: return "errSecReadOnly" | |
case errSecAuthFailed: return "errSecAuthFailed" | |
case errSecNoSuchKeychain: return "errSecNoSuchKeychain" | |
case errSecInvalidKeychain: return "errSecInvalidKeychain" | |
case errSecDuplicateKeychain: return "errSecDuplicateKeychain" | |
case errSecDuplicateCallback: return "errSecDuplicateCallback" | |
case errSecInvalidCallback: return "errSecInvalidCallback" | |
case errSecDuplicateItem: return "errSecDuplicateItem" | |
case errSecItemNotFound: return "errSecItemNotFound" | |
case errSecBufferTooSmall: return "errSecBufferTooSmall" | |
case errSecDataTooLarge: return "errSecDataTooLarge" | |
case errSecNoSuchAttr: return "errSecNoSuchAttr" | |
case errSecInvalidItemRef: return "errSecInvalidItemRef" | |
case errSecInvalidSearchRef: return "errSecInvalidSearchRef" | |
case errSecNoSuchClass: return "errSecNoSuchClass" | |
case errSecNoDefaultKeychain: return "errSecNoDefaultKeychain" | |
case errSecInteractionNotAllowed: return "errSecInteractionNotAllowed" | |
case errSecReadOnlyAttr: return "errSecReadOnlyAttr" | |
case errSecWrongSecVersion: return "errSecWrongSecVersion" | |
case errSecKeySizeNotAllowed: return "errSecKeySizeNotAllowed" | |
case errSecNoStorageModule: return "errSecNoStorageModule" | |
case errSecNoCertificateModule: return "errSecNoCertificateModule" | |
case errSecNoPolicyModule: return "errSecNoPolicyModule" | |
case errSecInteractionRequired: return "errSecInteractionRequired" | |
case errSecDataNotAvailable: return "errSecDataNotAvailable" | |
case errSecDataNotModifiable: return "errSecDataNotModifiable" | |
case errSecCreateChainFailed: return "errSecCreateChainFailed" | |
case errSecACLNotSimple: return "errSecACLNotSimple" | |
case errSecPolicyNotFound: return "errSecPolicyNotFound" | |
case errSecInvalidTrustSetting: return "errSecInvalidTrustSetting" | |
case errSecNoAccessForItem: return "errSecNoAccessForItem" | |
case errSecInvalidOwnerEdit: return "errSecInvalidOwnerEdit" | |
case errSecTrustNotAvailable: return "errSecTrustNotAvailable" | |
case errSecUnsupportedFormat: return "errSecUnsupportedFormat" | |
case errSecUnknownFormat: return "errSecUnknownFormat" | |
case errSecKeyIsSensitive: return "errSecKeyIsSensitive" | |
case errSecMultiplePrivKeys: return "errSecMultiplePrivKeys" | |
case errSecPassphraseRequired: return "errSecPassphraseRequired" | |
case errSecInvalidPasswordRef: return "errSecInvalidPasswordRef" | |
case errSecInvalidTrustSettings: return "errSecInvalidTrustSettings" | |
case errSecNoTrustSettings: return "errSecNoTrustSettings" | |
case errSecPkcs12VerifyFailure: return "errSecPkcs12VerifyFailure" | |
case errSecDecode: return "errSecDecode" | |
default: return "" | |
} | |
} | |
func statusMessage(status: OSStatus) -> String { | |
switch status { | |
case errSecSuccess: return "No error." | |
case errSecUnimplemented: return "Function or operation not implemented." | |
case errSecDskFull: return "Disk Full error." | |
case errSecIO: return "I/O error." | |
case errSecParam: return "One or more parameters passed to a function were not valid." | |
case errSecWrPerm: return " Write permissions error." | |
case errSecAllocate: return "Failed to allocate memory." | |
case errSecUserCanceled: return "User canceled the operation." | |
case errSecBadReq: return "Bad parameter or invalid state for operation." | |
case errSecInternalComponent: return "errSecInternalComponent" | |
case errSecCoreFoundationUnknown: return "errSecCoreFoundationUnknown" | |
case errSecNotAvailable: return "No keychain is available." | |
case errSecReadOnly: return "Read only error." | |
case errSecAuthFailed: return "Authorization/Authentication failed." | |
case errSecNoSuchKeychain: return "The keychain does not exist." | |
case errSecInvalidKeychain: return "The keychain is not valid." | |
case errSecDuplicateKeychain: return "A keychain with the same name already exists." | |
case errSecDuplicateCallback: return "The specified callback is already installed." | |
case errSecInvalidCallback: return "The specified callback is not valid." | |
case errSecDuplicateItem: return "The item already exists." | |
case errSecItemNotFound: return "The item cannot be found." | |
case errSecBufferTooSmall: return "The buffer is too small." | |
case errSecDataTooLarge: return "The data is too large." | |
case errSecNoSuchAttr: return "The attribute does not exist." | |
case errSecInvalidItemRef: return "The item reference is invalid." | |
case errSecInvalidSearchRef: return "The search reference is invalid." | |
case errSecNoSuchClass: return "The keychain item class does not exist." | |
case errSecNoDefaultKeychain: return "A default keychain does not exist." | |
case errSecInteractionNotAllowed: return "User interaction is not allowed." | |
case errSecReadOnlyAttr: return "The attribute is read only." | |
case errSecWrongSecVersion: return "The version is incorrect." | |
case errSecKeySizeNotAllowed: return "The key size is not allowed." | |
case errSecNoStorageModule: return "There is no storage module available." | |
case errSecNoCertificateModule: return "There is no certificate module available." | |
case errSecNoPolicyModule: return "There is no policy module available." | |
case errSecInteractionRequired: return "User interaction is required." | |
case errSecDataNotAvailable: return "The data is not available." | |
case errSecDataNotModifiable: return "The data is not modifiable." | |
case errSecCreateChainFailed: return "The attempt to create a certificate chain failed." | |
case errSecACLNotSimple: return "The access control list is not in standard simple form." | |
case errSecPolicyNotFound: return "The policy specified cannot be found." | |
case errSecInvalidTrustSetting: return "The specified trust setting is invalid." | |
case errSecNoAccessForItem: return "The specified item has no access control." | |
case errSecInvalidOwnerEdit: return "Invalid attempt to change the owner of this item." | |
case errSecTrustNotAvailable: return "No trust results are available." | |
case errSecUnsupportedFormat: return "Import/Export format unsupported." | |
case errSecUnknownFormat: return "Unknown format in import." | |
case errSecKeyIsSensitive: return "Key material must be wrapped for export." | |
case errSecMultiplePrivKeys: return "An attempt was made to import multiple private keys." | |
case errSecPassphraseRequired: return "Passphrase is required for import/export." | |
case errSecInvalidPasswordRef: return "The password reference was invalid." | |
case errSecInvalidTrustSettings: return "The Trust Settings Record was corrupted." | |
case errSecNoTrustSettings: return "No Trust Settings were found." | |
case errSecPkcs12VerifyFailure: return "MAC verification failed during PKCS12 Import." | |
case errSecDecode: return "Unable to decode the provided data." | |
default: return "" | |
} | |
} | |
} | |
public protocol CFStringHashable: Hashable, Equatable {} | |
extension CFStringHashable where Self: CFString { | |
public var hashValue: Int { | |
guard let string = self as? String else { return 0 } | |
return string.hashValue | |
} | |
public static func ==(lhs: Self, rhs: Self) -> Bool { | |
guard let lhsString = lhs as? String else { return false } | |
guard let rhsString = rhs as? String else { return false } | |
return lhsString == rhsString | |
} | |
} | |
extension CFString : CFStringHashable {} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment