Службы Связки Ключей Защищают Заметки


Документация для Keychain Services API оставляет желать лучшего. Одна вещь, которую я, кажется, не могу найти, - это детали доступа к защищенным заметкам, которые приложение Keychain Access позволяет добавлять и редактировать.

Любое озарение было бы очень ценно. Спасибо.

2 3

2 ответа:

Я понял,что вы можете извлечь данные с помощью инструмента командной строки безопасности. Защищенные заметки хранятся в виде универсальных паролей со следующими характеристиками:

class: "genp" - это то же самое, что и общий пароль

type<uint32>="note" - Это можно использовать для идентификации защищенных заметок, особенно при поиске (с помощью флага-C).

desc<blob>="secure note" - я не знаю, что вы можете искать на основе этого поля, но оно определенно идентифицирует элемент как защищенную заметку

0x00000007 <blob>= "Note name" - я не знаю. если вы можете получить это через API, но вы определенно можете получить это из инструмента командной строки

acct<blob>=<NULL> - это, по-видимому, общая характеристика защищенных заметок

Используйте команду security dump-keychain, чтобы найти все виды полезной информации о элементах связки ключей.

Просто чтобы расширить принятый ответ:

Действительно, "защищенные заметки" хранятся как просто специально отформатированные универсальные пароли. Таким образом, если вы создаете защищенную заметку, вы можете получить программный доступ к ней с помощью API Keychain Services: SecKeychainFindGenericPassword() или же ... security инструмент командной строки .

В качестве примера использования security, Если у вас есть защищенная заметка с именем "Testing Note":

отображение заметки в keychain access

Вам нужно будет найти "безопасные заметки" и название записка, "Проверочная записка". "Тип "(или desc поле) будет" примечание", а" сервис " (или svce поле, Имя записи связки ключей) будет фактическим названием Заметки. Похоже, что для каждого поля, которое вы укажете, оно должно быть точным, поэтому поиск "Testing *" или "Testing" не даст никаких результатов для нашей заметки.

Таким образом, вы можете использовать эту команду для поиска заметок с типом "secure note" и заголовком "Testing Note":

security find-generic-password -C note -s "Testing Note"

И вы получаете в качестве результат:

keychain: "/Users/USERNAME/Library/Keychains/login.keychain"
class: "genp"
attributes:
    0x00000007 <blob>="Testing Note"
    0x00000008 <blob>=<NULL>
    "acct"<blob>=<NULL>
    "cdat"<timedate>=0x32303134313231323137333130395A00  "20141212173109Z\000"
    "crtr"<uint32>=<NULL>
    "cusi"<sint32>=<NULL>
    "desc"<blob>="secure note"
    "gena"<blob>=<NULL>
    "icmt"<blob>=<NULL>
    "invi"<sint32>=<NULL>
    "mdat"<timedate>=0x32303134313231323137333130395A00  "20141212173109Z\000"
    "nega"<sint32>=<NULL>
    "prot"<blob>=<NULL>
    "scrp"<sint32>=<NULL>
    "svce"<blob>="Testing Note"
    "type"<uint32>="note"

Чтобы получить пароль для вывода, вам также нужно будет передать опцию -g команде security, и если вы явно не настроили security как доверенную / разрешенную программу для доступа к этому элементу связки ключей, она спросит вас, Хотите ли вы разрешить доступ к элементу связки ключей:

диалоговое окно с запросом, хотите ли вы разрешить доступ к элементу связки ключей

Глядя только на вывод пароля (вы можете использовать опцию -w, чтобы вывести только "пароль" или текст нашей заметки, однако вы не получите "декодированный" вывод, просто гекс), вы получаете:

security find-generic-password -C note -s "Testing Note" -w

(форматировано для ясности)

3c3f786d 6c207665 7273696f 6e3d2231 2e302220 656e636f
64696e67 3d225554 462d3822 3f3e0a3c 21444f43 54595045
20706c69 73742050 55424c49 4320222d 2f2f4170 706c652f
2f445444 20504c49 53542031 2e302f2f 454e2220 22687474
703a2f2f 7777772e 6170706c 652e636f 6d2f4454 44732f50
726f7065 7274794c 6973742d 312e302e 64746422 3e0a3c70
6c697374 20766572 73696f6e 3d22312e 30223e0a 3c646963
....... (and so on)

Не очень полезно! Если мы используем некоторый код python для его декодирования: (или любой язык по вашему выбору)

#!/usr/bin/env python3
import xml.etree.ElementTree as ET
import plistlib, pprint, binascii

# not full hex string for brevity!
hex_data = '''3c3f786d6c2076657273696f6e3d22312e3022206....'''

# decode hex into bytes
xml_bytes = binascii.unhexlify(hex_data)

# create ElementTree object since its an XML PList
ET.fromstring(xml_bytes)

# print out xml
print(ET.tostring(xml_bytes))

# or you can load it straight into a python object using plistlib
plist_dict = plistlib.loads(xml_bytes)
pprint.pprint(plist_dict)

Теперь мы кое-чего добились! Результатом его декодирования является:

<plist version="1.0">
<dict>
    <key>NOTE</key>
    <string>12345
abcdefghijklmnopqrstuvwxyz
HELLO WORLD
=)
</string>
    <key>RTFD</key>
    <data>
    cnRmZAAAAAADAAAAAgAAAAcAAABUWFQucnRmAQAAAC43AQAAKwAAAAEAAAAvAQAAe1xy
    dGYxXGFuc2lcYW5zaWNwZzEyNTJcY29jb2FydGYxMzQzXGNvY29hc3VicnRmMTYwCntc
    Zm9udHRibFxmMFxmc3dpc3NcZmNoYXJzZXQwIEhlbHZldGljYTt9CntcY29sb3J0Ymw7
    XHJlZDI1NVxncmVlbjI1NVxibHVlMjU1O30KXHBhcmRcdHg1NjBcdHgxMTIwXHR4MTY4
    MFx0eDIyNDBcdHgyODAwXHR4MzM2MFx0eDM5MjBcdHg0NDgwXHR4NTA0MFx0eDU2MDBc
    dHg2MTYwXHR4NjcyMFxwYXJkaXJuYXR1cmFsCgpcZjBcZnMyNCBcY2YwIDEyMzQ1XAph
    YmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5elwKSEVMTE8gV09STERcCj0pXAp9AQAAACMA
    AAABAAAABwAAAFRYVC5ydGYQAAAAXSaLVLYBAAAAAAAAAAAAAA==
    </data>
</dict>
</plist>

Таким образом, мы, очевидно, имеем пароль открытого текста в качестве значения для ключа " Примечание "(так как это то, как plists хранят словари), но что такое ключ" RTFD"? Глядя на него в двоичном виде, создается впечатление, что его некоторые вид файла rtfd:

b'rtfd\x00\x00\x00\x00\x03\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00TXT.rtf\x01 ......

Но сохраняя его как a .rtfd не работает, но потом я понял, что RTFDs, сохраненные из TextEdit, например, являются пакетами! Так как же это работает?.. вы действительно не можете сериализовать пакет в байты, так как это папка с файлами внутри, но затем при более тщательном поиске, (я нашелApple Type Code list , и там есть "com.яблоко.rtfd", но и " com.яблоко.плоский-rtfd", который, как он говорит, является" картонным " форматом!

Поэтому я использовал образец приложение от Apple , которое показывает подробную информацию о буфере обмена / картоне. Затем вы можете щелкнуть правой кнопкой мыши в Keychain access, "copy secure note":

копирование защищенной заметки в keychain access

А затем, если вы посмотрите на байты в ClipboardViewer, вы увидите, что они совпадают с не-шестнадцатеричными байтами в теге в plist.

Фу! Это было намного дольше, чем я ожидал.... Таким образом, вкратце, защищенная заметка - это просто общий пароль, с заголовком, а часть пароля - это Apple XML Plist, с текстовые данные, а также данные в картонном формате, пригодном для копирования в буфер обмена с помощью "Copy Secure note to clipboard".

Я надеюсь, что это прояснит, как хранятся защищенные заметки, так как действительно отсутствует API-функции, которые обращаются к защищенным заметкам, и ничего в официальном Keychain access API.