Skip to content

Instantly share code, notes, and snippets.

@santigz
Last active March 5, 2024 16:00
Show Gist options
  • Save santigz/601f4fd2f039d6ceb2198e2f9f4f01e0 to your computer and use it in GitHub Desktop.
Save santigz/601f4fd2f039d6ceb2198e2f9f4f01e0 to your computer and use it in GitHub Desktop.
Import Apple Keychain into pass

Import Apple Keychain into pass

This guide shows how to import into pass your passwords stored in Apple's Keychain Access.

Find your keychain file

The default kaychain file is ~/Library/Keychains/login.keychain.

Passwords under the "Local Items" keychain (the default since Mavericks to sync with iCloud) use a different file format and can not be exported via the Apple's security tool we use. If that is you case, create a new keychain and drag-and-drop the keys. Your new keychain should have the .keychain extension.

Export the keychain to plain text file

To export a keychain you can use Apple's secure utility from the terminal. Run:

security dump-database /full/path/to/mykeys.keychain > mykeys-dump.txt

A pop-up will appear asking for the keychain password for every key. This behaviour cannot be changed.

To automate this process, you can use script provided easy-export-apple-keychain.applescript that asks for the password one time and auto-fills all the pop-ups. Open and run it from the Script Editor app under /Applications/Utilities. When running, the process is invasive and you will see all windows appearing and closing, so just let it finish. Bear in mind you won't be able to use your desktop for some time. It takes ~1 second per password.

Import into pass

Install pass and the pass import plugin and run:

pass import apple-keychain mykeys-dump.txt

I recommend using the -C option (see the help).

Note: your public/private keys and certificates won't be imported. You should export them manually from Keychain Access.

And don't forget to delete your unencrypted dumped keys!

— apr 2019 sangonz.

Apple Keychain internals

This document provides a reference of study to analyze how the security tool works in macOS.

You can find the full source code in https://opensource.apple.com (direct link to the latest version at the time of this writing here).

Types of items in a keychain

Those are defined in OSX/libsecurity_keychain/lib/SecKeychainItem.h:

  • User and application defined passwords are class genp.
  • Passwords stored by Safari (and others?) are class inet.
typedef CF_ENUM(FourCharCode, SecItemClass)
{
    kSecInternetPasswordItemClass   = 'inet',
    kSecGenericPasswordItemClass    = 'genp',
    kSecAppleSharePasswordItemClass   CF_ENUM_DEPRECATED(10_0, 10_9, NA, NA) = 'ashp',
    kSecCertificateItemClass        = 0x80001000,
    kSecPublicKeyItemClass          = 0x0000000F,
    kSecPrivateKeyItemClass         = 0x00000010,
    kSecSymmetricKeyItemClass       = 0x00000011
};

Beware these categories do not follow exactly the UI, which also handles "Secure Notes": Keychain Access User Interface

Types of attributes

In the file OSX/libsecurity_keychain/lib/SecKeychainItem.h we find the next structure, whose comments are shown in the table below.

typedef CF_ENUM(FourCharCode, SecItemAttr)
{
    kSecCreationDateItemAttr        = 'cdat',
    kSecModDateItemAttr             = 'mdat',
    kSecDescriptionItemAttr         = 'desc',
    kSecCommentItemAttr             = 'icmt',
    kSecCreatorItemAttr             = 'crtr',
    kSecTypeItemAttr                = 'type',
    kSecScriptCodeItemAttr          = 'scrp',
    kSecLabelItemAttr               = 'labl',
    kSecInvisibleItemAttr           = 'invi',
    kSecNegativeItemAttr            = 'nega',
    kSecCustomIconItemAttr          = 'cusi',
    kSecAccountItemAttr             = 'acct',
    kSecServiceItemAttr             = 'svce',
    kSecGenericItemAttr             = 'gena',
    kSecSecurityDomainItemAttr      = 'sdmn',
    kSecServerItemAttr              = 'srvr',
    kSecAuthenticationTypeItemAttr  = 'atyp',
    kSecPortItemAttr                = 'port',
    kSecPathItemAttr                = 'path',
    kSecVolumeItemAttr              = 'vlme',
    kSecAddressItemAttr             = 'addr',
    kSecSignatureItemAttr           = 'ssig',
    kSecProtocolItemAttr            = 'ptcl',
    kSecCertificateType             = 'ctyp',
    kSecCertificateEncoding         = 'cenc',
    kSecCrlType                     = 'crtp',
    kSecCrlEncoding                 = 'crnc',
    kSecAlias                       = 'alis'
};
Name Description
cdat (read-only) Identifies the creation date attribute. You use this tag to get a value of type string that represents the date the item was created, expressed in Zulu Time format ("YYYYMMDDhhmmSSZ"). This format is identical to CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE (cssmtype.h). When specifying the creation date as input to a function (e.g. SecKeychainSearchCreateFromAttributes), you may alternatively provide a numeric value of type UInt32 or SInt64, expressed as seconds since 1/1/1904 (DateTimeUtils.h).
mdat (read-only) Identifies the modification date attribute. You use this tag to get a value of type string that represents the last time the item was updated, expressed in Zulu Time format ("YYYYMMDDhhmmSSZ"). This format is identical to CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE (cssmtype.h). When specifying the modification date as input to a function (e.g. SecKeychainSearchCreateFromAttributes), you may alternatively provide a numeric value of type UInt32 or SInt64, expressed as seconds since 1/1/1904 (DateTimeUtils.h).
desc Identifies the description attribute. You use this tag to set or get a value of type string that represents a user-visible string describing this particular kind of item (e.g. "disk image password").
icmt Identifies the comment attribute. You use this tag to set or get a value of type string that represents a user-editable string containing comments for this item.
crtr Identifies the creator attribute. You use this tag to set or get a value of type FourCharCode that represents the item's creator.
type Identifies the type attribute. You use this tag to set or get a value of type FourCharCode that represents the item's type.
scrp Identifies the script code attribute. You use this tag to set or get a value of type ScriptCode that represents the script code for all strings. (Note: use of this attribute is deprecated; string attributes should always be stored in UTF-8 encoding.)
labl Identifies the label attribute. You use this tag to set or get a value of type string that represents a user-editable string containing the label for this item.
invi Identifies the invisible attribute. You use this tag to set or get a value of type Boolean that indicates whether the item is invisible (i.e. should not be displayed).
nega Identifies the negative attribute. You use this tag to set or get a value of type Boolean that indicates whether there is a valid password associated with this keychain item. This is useful if your application doesn't want a password for some particular service to be stored in the keychain, but prefers that it always be entered by the user. The item (typically invisible and with zero-length data) acts as a placeholder to say "don't use me."
cusi Identifies the custom icon attribute. You use this tag to set or get a value of type Boolean that indicates whether the item has an application-specific icon. To do this, you must also set the attribute value identified by the tag kSecTypeItemAttr to a file type for which there is a corresponding icon in the desktop database, and set the attribute value identified by the tag kSecCreatorItemAttr to an appropriate application creator type. If a custom icon corresponding to the item's type and creator can be found in the desktop database, it will be displayed by Keychain Access. Otherwise, default icons are used. (Note: use of this attribute is deprecated; custom icons for keychain items are not supported in Mac OS X.)
acct Identifies the account attribute. You use this tag to set or get a string that represents the user account. This attribute applies to generic, Internet, and AppleShare password items.
svce Identifies the service attribute. You use this tag to set or get a string that represents the service associated with this item. This attribute is unique to generic password items.
gena Identifies the generic attribute. You use this tag to set or get a value of untyped bytes that represents a user-defined attribute. This attribute is unique to generic password items.
sdmn Identifies the security domain attribute. You use this tag to set or get a value that represents the Internet security domain. This attribute is unique to Internet password items.
srvr Identifies the server attribute. You use this tag to set or get a value of type string that represents the Internet server's domain name or IP address. This attribute is unique to Internet password items.
atyp Identifies the authentication type attribute. You use this tag to set or get a value of type SecAuthenticationType that represents the Internet authentication scheme. This attribute is unique to Internet password items.
port Identifies the port attribute. You use this tag to set or get a value of type UInt32 that represents the Internet port number. This attribute is unique to Internet password items.
path Identifies the path attribute. You use this tag to set or get a string value that represents the path. This attribute is unique to Internet password items.
vlme Identifies the volume attribute. You use this tag to set or get a string value that represents the AppleShare volume. This attribute is unique to AppleShare password items. Note: AppleShare passwords are no longer used by OS X as of Leopard (10.5); Internet password items are used instead.
addr Identifies the address attribute. You use this tag to set or get a string value that represents the AppleTalk zone name, or the IP or domain name that represents the server address. This attribute is unique to AppleShare password items. Note: AppleShare passwords are no longer used by OS X as of Leopard (10.5); Internet password items are used instead.
ssig Identifies the server signature attribute. You use this tag to set or get a value of type SecAFPServerSignature that represents the server signature block. This attribute is unique to AppleShare password items. Note: AppleShare passwords are no longer used by OS X as of Leopard (10.5); Internet password items are used instead.
ptcl Identifies the protocol attribute. You use this tag to set or get a value of type SecProtocolType that represents the Internet protocol. This attribute applies to AppleShare and Internet password items.
ctyp Indicates a CSSM_CERT_TYPE type.
cenc Indicates a CSSM_CERT_ENCODING type.
crtp Indicates a CSSM_CRL_TYPE type.
crnc Indicates a CSSM_CRL_ENCODING type.
alis Indicates an alias.

Protocol codes

In the file OSX/libsecurity_keychain/lib/SecKeychain.h we find the char code for the protocols supported, which may contain spaces or have uncommon spellings to fit into 4 characters:

typedef CF_ENUM(FourCharCode, SecProtocolType)
{
    kSecProtocolTypeFTP         = 'ftp ',
    kSecProtocolTypeFTPAccount  = 'ftpa',
    kSecProtocolTypeHTTP        = 'http',
    kSecProtocolTypeIRC         = 'irc ',
    kSecProtocolTypeNNTP        = 'nntp',
    kSecProtocolTypePOP3        = 'pop3',
    kSecProtocolTypeSMTP        = 'smtp',
    kSecProtocolTypeSOCKS       = 'sox ',
    kSecProtocolTypeIMAP        = 'imap',
    kSecProtocolTypeLDAP        = 'ldap',
    kSecProtocolTypeAppleTalk   = 'atlk',
    kSecProtocolTypeAFP         = 'afp ',
    kSecProtocolTypeTelnet      = 'teln',
    kSecProtocolTypeSSH         = 'ssh ',
    kSecProtocolTypeFTPS        = 'ftps',
    kSecProtocolTypeHTTPS       = 'htps',
    kSecProtocolTypeHTTPProxy   = 'htpx',
    kSecProtocolTypeHTTPSProxy  = 'htsx',
    kSecProtocolTypeFTPProxy    = 'ftpx',
    kSecProtocolTypeCIFS        = 'cifs',
    kSecProtocolTypeSMB         = 'smb ',
    kSecProtocolTypeRTSP        = 'rtsp',
    kSecProtocolTypeRTSPProxy   = 'rtsx',
    kSecProtocolTypeDAAP        = 'daap',
    kSecProtocolTypeEPPC        = 'eppc',
    kSecProtocolTypeIPP         = 'ipp ',
    kSecProtocolTypeNNTPS       = 'ntps',
    kSecProtocolTypeLDAPS       = 'ldps',
    kSecProtocolTypeTelnetS     = 'tels',
    kSecProtocolTypeIMAPS       = 'imps',
    kSecProtocolTypeIRCS        = 'ircs',
    kSecProtocolTypePOP3S       = 'pops',
    kSecProtocolTypeCVSpserver  = 'cvsp',
    kSecProtocolTypeSVN         = 'svn ',
    kSecProtocolTypeAny         =  0
};
(*
@header
Export Apple's Keychain Access passwords easily
@discussion
April 2019 sangonz - https://github.com/sangonz
Thanks to https://github.com/lifepillar/CSVKeychain - see Lifepillar's awesome
work if you want more information.
This is just a minimalist script to only export a keychain to be easily used
by https://github.com/sangonz/pass-import.
@license
Copyright (c) 2011-2018, Lifepillar
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*)
-- Select keychain file
set defaultPath to path to keychain folder from user domain
set keychain to choose file with prompt "Please select the keychain file to be exported:" of type {"com.apple.keychain"} default location defaultPath without invisibles, multiple selections allowed and showing package contents
-- Handle export file
set exportPath to (keychain as text) & "-export.txt"
tell application "Finder"
if exists file exportPath then
display dialog "The export file already exists: " & (POSIX path of exportPath) buttons {"Exit"} default button "Exit"
return
end if
end tell
set exportPath to (POSIX path of exportPath)
-- Get user password
display dialog "Type password to unlock keychain items" default answer "" with title "Set password" with icon note with hidden answer
set thePassword to the text returned of the result
-- Execute the exportation
do shell script "security -q dump-keychain -d " & quoted form of POSIX path of the keychain & " &>" & quoted form of exportPath & " &"
-- Autofill the passwords
delay 0.5
tell application "System Events"
repeat while exists (processes where name is "SecurityAgent")
tell process "SecurityAgent"
set frontmost to true
try
keystroke thePassword
delay 0.1
keystroke return
delay 0.1
on error
-- Skip error
end try
end tell
delay 0.5
end repeat
end tell
display dialog "Finished! Exported in " & exportPath
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment