HSM, использующий метку ключевого объекта в PKCS11

#python #encryption #cryptography #pkcs#11 #hsm

#python #шифрование #криптография #pkcs #11 #hsm

Вопрос:

Этот блок кода загружает cryptoki.so библиотека и получение информации о слоте. Это получение списка объектов в слоте num. 0. Мне не нужно обращаться ко всем ключам для выполнения нескольких функций, только к определенной паре ключей. Есть ли способ получить один желаемый токен, используя имя метки, идентификатор объекта или дескриптор?

 pkcs11 = PyKCS11.PyKCS11Lib()
pkcs11.load(lib)
pkcs11.initialize()
info = pkcs11.getInfo()
i = pkcs11.getSlotInfo(0)
pkcs11.openSession(0)

print "Library manufacturerID: "   info.manufacturerID

slots = pkcs11.getSlotList()
print "Available Slots:", len(slots)

for s in slots:
try:
    i = pkcs11.getSlotInfo(s)
    print "Slot no:", s
    print format_normal % ("slotDescription", i.slotDescription.strip())
    print format_normal % ("manufacturerID", i.manufacturerID.strip())

    t = pkcs11.getTokenInfo(s)
    print "TokenInfo"
    print format_normal % ("label", t.label.strip())
    print format_normal % ("manufacturerID", t.manufacturerID.strip())
    print format_normal % ("model", t.model.strip())


    session = pkcs11.openSession(s)
    print "Opened session 0xX" % session.session.value()
    if pin_available:
        try:
            session.login(pin=pin)
        except:
            print "login failed, exception:", str(sys.exc_info()[1])

    objects = session.findObjects()
    print
    print "Found %d objects: %s" % (len(objects), [x.value() for x in objects])
  

В конкретном скрипте, который я запускаю, определено только несколько команд, например, -pin --sign --decrypt --lib нужно ли мне определять общую pkcs11-tool , например, --init-token or --token-label передавать ее в качестве аргумента при выполнении моего скрипта? Или я могу напрямую присвоить переменную желаемому LabelName в скрипте python?

Итак, из командной строки я запускаю

$./Test.py --pin=pass и получаем следующее

 Library manufacturerID: Safenet, Inc.                   
Available Slots: 4
Slot no: 0
  slotDescription: ProtectServer K5E:00045
  manufacturerID: SafeNet Inc.
TokenInfo
  label: CKM
  manufacturerID: SafeNet Inc.
  model: K5E:PL25
Opened session 0x00000002

Found 52 objects: [5021, 5022, 5014, 5016, 4, 5, 6, 7, 8, 9, 16, 18, 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 5313, 5314, 4982, 5325, 5326, 5328, 5329, 5331, 5332, 5335, 5018, 4962, 5020, 4963, 5357, 5358, 5360, 5361, 5363, 5364, 5366, 5367, 5369, 5370, 5372, 5373, 5375, 5376]
  

В конечном итоге я пытаюсь заставить только один из этих объектов выполнить некоторые тесты.Например objectID = 201603040001 , содержит файл private / cert. Я хочу указать этот конкретный дескриптор. Фактическая метка выглядит примерно так 000103...3A0 . Как я могу определить это, чтобы я не получал остальные объекты внутри библиотеки.

Вот список всего нескольких объектов HSM

  HANDLE LABEL                  TYPE                       OBJECT-ID
  5314 00000103000003A1       X509PublicKeyCertificate   201603040001
  5313 00000103000003A1       RSAPrivateKey              201603040001
  

Я пытаюсь извлечь только одну из меток.

Вот определенное использование

 def usage():
    print "Usage:", sys.argv[0],
    print "[-p pin][--pin=pin]",
    print "[-s slot][--slot=slot]",
    print "[-c lib][--lib=lib]",
    print "[-h][--help]",
    print "[-o][--opensession]"

try:
    opts, args = getopt.getopt(sys.argv[1:], "p:c:Sd:h:s", ["pin=", "lib=", "sign", "decrypt", "help","slot="])
except getopt.GetoptError:
    # print help information and exit:
    usage()
    sys.exit(2)
  

Я не знаю, как я могу добавить аргумент, чтобы я мог использовать --sign только определенную метку. Завершите игру, которую я хочу использовать $./Test.py --pin=pass --sign --label "00000103000003A4" , или с помощью дескриптора $./Test.py --pin=pass --sign --handle=5313

ОБНОВЛЕНО из предложенных комментариев ниже. по-прежнему возникают проблемы с получением атрибутов для закрытого ключа и сертификата rsa. Использование определенного токена сработало, но эти объекты внутри него возвращают неверные типы атрибутов

    t = pkcs11.getTokenInfo(s)
    print "TokenInfo"
    if 'CKM' == t.label.decode('ascii').strip():
            tokenInfo = pkcs11.getTokenInfo(slot)
    if '00000103000003A1' == tokenInfo.label.decode('ascii').strip():
            print format_normal % ("label", t.label.strip())
            print format_normal % ("manufacturerID", t.manufacturerID.strip())
            print format_normal % ("model", t.model.strip())


            session = pkcs11.openSession(s)
    print("Opened session 0xX" % session.session.value())
    if pin_available:
        try:
            if (pin is None) and 
                    (PyKCS11.CKF_PROTECTED_AUTHENTICATION_PATH amp; t.flags):
                print("nEnter your PIN for %s on the pinpad" % t.label.strip())
            session.login(pin=pin)
        except:
            print("login failed, exception:", str(sys.exc_info()[1]))
            break

    objects = session.findObjects([(CKA_LABEL, "00000103000003A4")])
    print()
    print("Found %d objects: %s" % (len(objects), [x.value() for x in objects]))

    all_attributes = list(PyKCS11.CKA.keys())
    # only use the integer values and not the strings like 'CKM_RSA_PKCS'
    all_attributes.remove(PyKCS11.CKA_PRIVATE_EXPONENT)
    all_attributes.remove(PyKCS11.CKA_PRIME_1)
    all_attributes.remove(PyKCS11.CKA_PRIME_2)
    all_attributes.remove(PyKCS11.CKA_EXPONENT_1)
    all_attributes.remove(PyKCS11.CKA_EXPONENT_2)
    all_attributes.remove(PyKCS11.CKA_COEFFICIENT)
    all_attributes = [e for e in all_attributes if isinstance(e, int)]

          n_obj = 1
    for o in objects:
        print()
        print((red   "==================== Object: %d ===================="   normal) % o.value())
        n_obj  = 1
        try:
            attributes = session.getAttributeValue(o, all_attributes)
        except PyKCS11.PyKCS11Error as e:
            continue    
        attrDict = dict(zip(all_attributes, attributes))
        if attrDict[PyKCS11.CKA_CLASS] == PyKCS11.CKO_PRIVATE_KEY 
           and attrDict[PyKCS11.CKA_KEY_TYPE] == PyKCS11.CKK_RSA:
            m = attrDict[PyKCS11.CKA_MODULUS]
            e = attrDict[PyKCS11.CKA_PUBLIC_EXPONENT]
            if m and e:
                mx = eval(b'0x'   ''.join("X" %c for c in m))
                ex = eval(b'0x'   ''.join("X" %c for c in e))
            if sign:
                try:
                    toSign = "12345678901234567890123456789012"  # 32 bytes, SHA256 digest
                    print("* Signing with object 0xX following data: %s" % (o.value(), toSign))
                    signature = session.sign(o, toSign)
                    sx = eval(b'0x'   ''.join("X" % c for c in signature))
                    print("Signature:")
                    print(dump(''.join(map(chr, signature))))
                    if m and e:
                        print("Verifying using following public key:")
                        print("Modulus:")
                        print(dump(''.join(map(chr, m))))
                        print("Exponent:")
                        print(dump(''.join(map(chr, e))))
                        decrypted = pow(sx, ex, mx)  # RSA
                        print("Decrypted:")
                        d = binascii.unhexlify(hexx(decrypted))
                        print(dump(d))
                        if toSign == d[-20:]:
                            print("*** signature VERIFIED!n")
  

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

 Slot no: 0
  slotDescription: ProtectServer K5E:00045
  manufacturerID: SafeNet Inc.
TokenInfo
Opened session 0x00000002

Found 2 objects: [5328, 5329]

==================== Object: 5328 ====================

==================== Object: 5329 ====================
  

Комментарии:

1. (Я здесь тоже новичок, но) пожалуйста, рассмотрите возможность публикации нового вопроса или обновления уже существующего вместо того, чтобы загрязнять этот вопрос «поправками». Таким образом, вопросы и ответы на них намного легче отслеживать и могут помочь другим людям с аналогичными проблемами. Более того, если вы обновили свой уже существующий вопрос об атрибутах, он появится вверху в списке активных вопросов и покажет, что вы добились определенного прогресса (что, в свою очередь, привлекает некоторое внимание и, в конечном счете, ответы). Удачи с вашим проектом!

Ответ №1:

Вы можете работать только с одним токеном, проверяя его метку перед использованием, например:

 tokenInfo = pkcs11.getTokenInfo(slot)
if 'DesiredTokenLabel' == tokenInfo.label.decode('ascii').strip():
    # Start working with this particular token
    session = pkcs11.openSession(s)
  

Вы можете перечислить только определенный объект, используя аргумент шаблона для findObjects вызова, например:

 # get objects labelled "PRIV"
objects = session.findObjects([(CKA_LABEL, "PRIV")])

# get all private key objects
objects = session.findObjects([(CKA_CLASS, CKO_PRIVATE_KEY)])

# get all private key objects labelled "PRIV"
objects = session.findObjects([(CKA_CLASS, CKO_PRIVATE_KEY),(CKA_LABEL, "PRIV")])

# get all RSA private key objects labelled "PRIV"
objects = session.findObjects([(CKA_CLASS, CKO_PRIVATE_KEY),(CKA_KEY_TYPE, CKK_RSA),(CKA_LABEL, "PRIV")])
  

Ниже приведен пример кода с жестко заданными параметрами:

 from PyKCS11 import *

pkcs11 = PyKCS11.PyKCS11Lib()
pkcs11.load("your module path...")
slots = pkcs11.getSlotList()
for s in slots:
    t = pkcs11.getTokenInfo(s)
    if 'CKM' == t.label.decode('ascii').strip():
        session = pkcs11.openSession(s)
        objects = session.findObjects([(CKA_LABEL, "00000103000003A1")])
        print ("Found %d objects: %s" % (len(objects), [x.value() for x in objects]))
  

Пожалуйста, обратите внимание, что это Python 3, поскольку я не могу использовать PyKCS11 в Python 2.x прямо сейчас.

Дополнительные (случайные) примечания Soma:

  • не полагайтесь на дескрипторы — они могут (и будут) отличаться для разных запусков программы

  • аргументы командной строки вашей программы зависят от вас — вы должны сами решить, нужны ли вашей программе такие аргументы, как --token-label

Отказ от ответственности: я не увлекаюсь python, поэтому, пожалуйста, подтвердите мои мысли

Удачи!

РЕДАКТИРОВАТЬ (относительно вашего недавнего редактирования)>

Ошибка (скорее всего) не отображается, поскольку исключение перехватывается и игнорируется:

 try:
    attributes = session.getAttributeValue(o, all_attributes)
except PyKCS11.PyKCS11Error as e:
    continue
  

Комментарии:

1. Спасибо за информацию, я изучаю это. Изначально у меня был шаблон атрибутов, реализованный в виде кортежа (например,) `attributes = [ («CKA_CLASS», PyKCS11.CKA_CLASS), («CKA_LABEL», PyKCS11.CKA_LABEL), чтобы перечислить пару. По сути, этот шаблон становится неактуальным, потому что вы можете перечислять только определенный объект, используя аргумент шаблона для вызова findObjects, например ?

2. @DJ2 Точно, findObjects метод позволяет указать шаблон фильтрации. Этот шаблон представляет собой «список кортежей». Шаблон в вашем комментарии выглядит странно, поскольку его кортежи должны иметь форму (атрибут, значение) . Посмотрите на примеры PYKCS11

3. @DJ2 Что касается редактирования комментариев — я использую следующую стратегию: 1. попробуйте отредактировать комментарий, 2. ругайтесь, 3. скопируйте комментарий в буфер обмена 4. удалите комментарий 5. опубликуйте комментарий снова 🙂

4. @DJ2, который напоминает мне: владелец сообщения всегда уведомляется

5. Я смог захватить только токен ‘00000103000003A1’ и распечатать в нем 2 объекта, закрытый ключ RSA и сертификат x509. Однако я получаю сообщение об ошибке print format_long % (PyKCS11.CKA[q], PyKCS11.CKO[a], a) KeyError: ('CKA_CLASS', 0) в опубликованном вами блоке выше, что единственный шаблон, который я должен использовать для извлечения атрибутов конкретного объекта и избавления от имеющегося у меня шаблона кортежа? vlp