Пример #1
0
def test_add_remove_cert():
    '''
    Test add_cert
    Метод `CertStore.add_cert(cert) добавляет сертификат `cert` в хранилище.
    Объект сертификата может быть загружен из сообщения, взят из другого
    хранилища или получен дублированием с помощью функции `Cert.duplicate()`.

    Если экземпляр сертификата привязан к хранилищу, его можно удалить оттуда
    вызовом метода `Cert.remove_from_store()`. При этом им можно продолжать
    пользоваться, пока он не будет удален из памяти.

    '''
    my = csp.CertStore(None, b"MY")
    n1 = len(list(my))
    with open(case_path('logical.cms'), 'rb') as f:
        testdata = f.read()
    msg = csp.CryptMsg(testdata)
    ids = []
    for crt in csp.CertStore(msg):
        my.add_cert(crt)
        my.add_cert(crt.duplicate())
        ids.append(crt.thumbprint())
    assert len(ids)
    for cert_id in ids:
        cs = list(my.find_by_thumb(cert_id))
        for cert in cs:
            cert.remove_from_store()
    print(len(list(my)), n1)
    assert len(list(my)) == n1
Пример #2
0
def test_memory_store():
    '''
    Test: memory store
    Хранилище сертификатов может быть создано в памяти вызовом конструктора
    `CertStore()` без параметров.

    '''
    my = csp.CertStore(None, b"MY")
    cert = list(my.find_by_name(test_cn))[0]

    cs = csp.CertStore()

    # метод `CertStore.add_cert(c)` добавляет сертификат `c` в хранилище.
    cs.add_cert(cert)

    assert len(list(cs))
Пример #3
0
def setup_package():
    '''
    Создание тестового ключевого контейнера и сертификата.
    '''
    assert cryptoapi.gen_key(test_container, local=test_local)
    cs = csp.CertStore(None, b"MY")
    certs = list(cs.find_by_name(test_cn))
    if not certs:
        if not os.path.isfile(test_cer_fn):
            req_params = dict(
                Attributes=[(CN, test_cn)],
                KeyUsage=[
                    'dataEncipherment', 'nonRepudiation', 'keyEncipherment',
                    'digitalSignature'
                ],
                EKU=[
                    csp.szOID_PKIX_KP_EMAIL_PROTECTION,
                    csp.szOID_PKIX_KP_CLIENT_AUTH
                ],
                # CertificatePolicies=[('1.2.643.100.113.1', []),
                # ('1.2.643.100.113.2', [])],
            )
            request = cryptoapi.create_request(test_container,
                                               req_params,
                                               local=test_local)
            open(test_req_fn, 'wb').write(b64encode(request))
            print('''
Creating certificate request in file '{req}'. Submit request to
CA and save certificate in file '{cer}'. Then re-run tests.
            '''.format(req=test_req_fn, cer=test_cer_fn))
            assert False
        else:
            cert = open(test_cer_fn, 'rb').read()
            cryptoapi.bind_cert_to_key(test_container, cert, local=test_local)
            os.remove(test_cer_fn)
Пример #4
0
def test_store_iter():
    '''
    Итерация по контейнеру перебирает все хранящиеся в нем сертификаты.
    '''
    cs = csp.CertStore(None, b"MY")
    for c in cs:
        assert c
Пример #5
0
def test_sign_data():
    '''
    При создании нового пустого сообщения, конструктору передается либо
    контекст, либо конструктор вызывается без параметров.

    Метод `CryptMsg.add_signer_cert(c)` сохраняет в сообщении сертификат `c`,
    которым будет подписано сообщение. Таким образом можно добавлять несколько
    подписантов и их сертификатов.

    Метод `CryptMsg.sign_data(s)` создает сообщение, закодированное в PKCS7,
    подписанное всеми сертификатами из списка. Подписи и сертификаты входят в
    байтовую строку, которая возвращается функцией.
    '''
    ctx = csp.Crypt(
        test_container,
        PROV_GOST,
        0, test_provider
    )
    cs = csp.CertStore(ctx, b"MY")
    cert = list(cs.find_by_name(test_cn))[0]
    mess = csp.CryptMsg()
    print(csp.CertInfo(cert).name())
    data = mess.sign_data(b'hurblewurble', cert, False)
    assert len(data)
    return data
Пример #6
0
def test_store_in_context():
    '''
    Первый параметр позволяет связать хранилище с контекстом провайдера.
    '''
    context = test_context_simple()
    cs = csp.CertStore(context, b"MY")
    assert cs
Пример #7
0
def test_verify_hash():
    sign, data = test_sign_hash()
    ctx = test_cert_acquire_key()
    cs = csp.CertStore(ctx, b"MY")
    cert = list(c for c in cs.find_by_name(bytes(test_cn)) if csp.CertInfo(c).name() == b'CN=' + test_cn)[0]
    length = 0 if test_cn.endswith(b'2012') else 2001
    hash1 = csp.Hash(ctx, data, length)
    assert hash1.verify(cert, sign)
Пример #8
0
def main():
    global ctxname
    try:
        ctx = csp.Crypt(b'{0}'.format(ctxname), csp.PROV_GOST_2001_DH, 0 | silent, provider)
    except:
        ctx = None
    if ctx is None:
        ctx = csp.Crypt(
            b'{0}'.format(ctxname), csp.PROV_GOST_2001_DH, csp.CRYPT_NEWKEYSET | silent, provider)
    msg = csp.CryptMsg(ctx)
    cs = csp.CertStore(ctx, b"My")

    rec_c = list(cs.find_by_name(b'123456789abcdef'))[0]
    ci = csp.CertInfo(rec_c)
    print(ci.name(), ci.issuer(), hexlify(ci.serial()))
    print(ci.not_before(), ci.not_after())

    msg.add_recipient(rec_c)
    data = msg.encrypt_data(b'Test byte string')
    print(len(data))

    #rec_c = list(cs.find_by_name(b'test'))[0]
    cs2 = csp.CertStore()
    cs2.add_cert(rec_c)
    encrypted = csp.CryptMsg(data)
    print('type:', encrypted.get_type())
    print('data:', encrypted.get_data())
    return_data = encrypted.decrypt(cs2)
    print(return_data)

    signed = msg.sign_data(b'Test signed data', rec_c)
    print(len(signed))

    msg2 = csp.CryptMsg(signed, ctx)
    info = csp.CertInfo(msg2, 0)
    print('version:', info.version())
    print('type:', msg2.get_type())
    print(msg2.verify(0))
    detached = msg.sign_data(b'Test signed data', rec_c, True)
    print(len(detached))
    sig = csp.Signature(detached, ctx)
    print(sig.verify_data(b'Test signed data', 0))
    print(sig.verify_data(b'Test zigned Data', 0))
    sig2 = csp.CryptMsg(open('tests/data1.p7s', 'rb').read())
    print('sig type:', sig2.get_type())
    print('sig data:', sig2.get_data())
Пример #9
0
def test_certinfo_sign_algorithm():
    '''
    Test: sign algorithm
    Метод `CertInfo.sign_algorithm()` возвращает идентификатор алгоритма ЭЦП.
    '''
    cs = csp.CertStore(None, b"MY")
    cert = list(cs.find_by_name(test_cn))[0]
    assert csp.CertInfo(cert).sign_algorithm() == '1.2.643.2.2.3'
Пример #10
0
def test_extract_cert():
    '''
    Метод `Cert.extract()` возвращает закодированный сертификат в виде байтовой строки.
    '''
    cs = csp.CertStore(None, b"MY")
    cert = list(c for c in cs.find_by_name(bytes(test_cn)) if csp.CertInfo(c).name() == b'CN=' + test_cn)[0]
    cdata = cert.extract()
    assert len(cdata)
    return cdata
Пример #11
0
def test_import_public_key_info():
    context = csp.Crypt(test_container, PROV_GOST, 0, test_provider)
    cs = csp.CertStore(None, b"MY")
    cert = list(c for c in cs.find_by_name(bytes(test_cn)) if csp.CertInfo(c).name() == b'CN=' + test_cn)[0]
    pkey = context.import_public_key_info(cert)
    assert pkey
    keyBlob = pkey.encode(None)
    print(len(keyBlob))
    assert len(keyBlob) >= 100
Пример #12
0
def test_cert_subject_id():
    '''
    Метод `Cert.subject_id()` возвращает идентификатор SubjectKeyId сертификата в виде бинарной
    строки. Для перевода в обычную строку, может потребоваться кодирование в
    base64 или вызов функции `hexlify()`.
    '''
    cs = csp.CertStore(None, b"MY")
    ids = [cert.subject_id() for cert in cs]
    assert len(ids) and all(len(x) == 20 for x in ids)
Пример #13
0
def test_cert_from_detached():
    '''
    Конструктору хранилища сертификатов `CertStore(msg)` можно передать экземпляр
    класса `CryptMsg` или `Signature`. Через это хранилище можно извлекать
    хранящиеся в сообщении или подписи сертификаты.
    '''
    data = test_detached_sign()
    sgn = csp.Signature(data)
    cs = csp.CertStore(sgn)
    assert len(list(cs))
Пример #14
0
def test_certinfo_issuer():
    '''
    Test: issuer
    Метод `Cert.issuer()` возвращает информацию о том, кто выдал сертификат,
    работает аналогично `Cert.name()`.
    '''
    cs = csp.CertStore(None, b"MY")
    issuers = list(csp.CertInfo(cert).issuer() for cert in cs)
    print((issuers))
    assert all(s for s in issuers)
Пример #15
0
def test_duplicate_cert():
    '''
    Метод `Cert.duplicate()` создает веременную копию серта, не сохраняемую в
    хранилище.
    '''
    cs = csp.CertStore(None, b"MY")
    for c in cs:
        cdup = c.duplicate()
        print((b64encode(c.thumbprint())))
        print((b64encode(cdup.thumbprint())))
Пример #16
0
def _cert_thumb():
    '''
    Метод `Cert.thumb()` возвращает отпечаток сертификата в виде бинарной
    строки. Для перевода в обычную строку, может потребоваться кодирование в
    base64.
    '''
    cs = csp.CertStore(None, b"MY")
    thumbs = [cert.thumbprint() for cert in cs]
    assert thumbs
    return thumbs[0]
Пример #17
0
def test_cert_find_by_name():
    '''
    Test: find by name
    Метод `CertStore.find_by_name(s)` перечисляет все сертификаты, в RDN которых
    так или иначе встречается байтовая строка `s`.
    '''
    name = test_cn
    cs = csp.CertStore(None, b"MY")
    res = list(cs.find_by_name(name))
    assert len(res)
Пример #18
0
def test_cert_find_by_thumb():
    '''
    Test: find by thumb
    Метод `CertStore.find_by_thumb(s)` перечисляет все сертификаты с
    отпечатком, равным байтовой строке `s`.
    '''
    thumb = _cert_thumb()
    cs = csp.CertStore(None, b"MY")
    res = list(cs.find_by_thumb(thumb))
    assert len(res)
Пример #19
0
def test_certinfo_name():
    '''
    Метод `Cert.name()` возвращает строку с RDN сертификата в виде бинарной
    строки. Для дальнейшей работы с ней может потребоваться модуль `RDN` и ее
    перекодирование в unicode.
    '''
    cs = csp.CertStore(None, b"MY")
    names = list(csp.CertInfo(cert).name() for cert in cs)
    print(names)
    assert all(name for name in names)
Пример #20
0
def test_cert_acquire_key():
    '''
    Контекст криптопровайдера может быть создан путем вызова конструктора на
    объект `Cert`. При этом вернется контекст, связанный с контейнером ключа
    данного сертификата. Если получить ключ не удастся, будет брошено
    исключение `ValueError`.
    '''
    cs = csp.CertStore(None, b"MY")
    cert = list(c for c in cs.find_by_name(bytes(test_cn)) if csp.CertInfo(c).name() == b'CN=' + test_cn)[0]
    ctx = csp.Crypt(cert)
    return ctx
Пример #21
0
def test_cert_from_data():
    '''
    Конструктор `Cert(s)`, при передаче ему байтовой строки `s`, декодирует и
    загружает из нее новый экземпляр сертификата, не сохраненный в хранилище.
    При необходимости его можно туда добавить функцией `CertStore.add_cert()`.
    '''
    cdata = test_extract_cert()
    print(len(cdata))
    newc = csp.Cert(cdata)
    assert newc
    memstore = csp.CertStore()
    memstore.add_cert(newc)
    assert len(list(memstore)) == 1
Пример #22
0
def test_encrypt_data():
    '''
    Шифрование сообщения представлено методом `CryptMsg.encrypt_data(s)`, где
    `s` -- бинарная строка. Результатом является шифрованный блок бинарных
    данных. Предварительно необходимо задать один или более сертификатов
    получателя функцией `CryptMsg.add_recipient_cert(cert)`. В Python 3
    необходимо перевести шифруемую строку в какую-нибудь 8-битную кодировку.
    '''
    cs = csp.CertStore(None, b"MY")
    re_cert = list(cs.find_by_name(test_cn))[0]
    msg = csp.CryptMsg()
    msg.add_recipient(re_cert)
    data = msg.encrypt_data(bindata)
    assert data
    return data
Пример #23
0
def test_decrypt_data():
    '''
    Зашифрованный блок данных можно передавать по незащищенному каналу.
    Расшифровка производится созданием пустого экземпляра `CryptMsg` и вызовом
    от него функции `CryptMsg.decrypt_data(data)`, где `data` -- бинарная
    строка с шифрованными данными. Пустое сообщение можно создать вызовом
    коструктора без параметрое, либо передать конструктору контекст
    криптопровайдера. Тогда ключи расшифровки будут извлекаться из хранилища
    ключей для этого контекста.

    '''
    data = test_encrypt_data()
    decrcs = csp.CertStore(None, b'MY')
    msg = csp.CryptMsg(data)
    assert msg
    res = msg.decrypt(decrcs)
    assert res == bindata
Пример #24
0
def test_verify_file():
    '''
    Проверка отсоединенной подписи, созданной через командную строку.
    '''
    names = ('data1', 'data2')
    for name in names:
        with open(case_path('{0}.bin'.format(name)), 'rb') as f:
            data = f.read()
        with open(case_path('{0}.p7s'.format(name)), 'rb') as f:
            sigdata = f.read()
        sign = csp.Signature(sigdata)
        print(name, sign.num_signers())
        if sign.num_signers() <= 0:
            continue
        for c in csp.CertStore(sign):
            print(b64encode(c.thumbprint()))
        assert all(sign.verify_data(data, n) for n in range(sign.num_signers()))
Пример #25
0
def _test_verifying():
    thumb = get_test_thumb()
    cert = cryptoapi.get_certificate(thumb)
    cs = csp.CertStore(None, b'My')
    wrong_certs = list(x.extract() for x in cs
                       if hexlify(x.thumbprint()) != thumb)

    sig = cryptoapi.sign(thumb, msg, False)
    assert sig
    assert cryptoapi.check_signature(cert, sig, msg)
    assert not cryptoapi.check_signature(cert, sig, msg[:-1])
    assert cryptoapi.check_signature(None, sig, msg)
    assert not cryptoapi.check_signature(None, sig, msg[:-1])
    if len(wrong_certs):
        assert not any(
            cryptoapi.check_signature(c, sig, msg) for c in wrong_certs)
    return sig
Пример #26
0
def tease(s):
    for f in range(10):
        cs = csp.CertStore(None, "MY")
        lst = list(cs)
        print(len(lst))
        del lst
        del cs
    for n in range(10):
        cc = csp.Cert(s)
        print(list(cc.eku()))
        del cc
    for n in range(100):
        cont = b'123456789abcdefj'
        ctx = csp.Crypt(cont, 75, 0)
        del ctx
        req = cryptoapi.create_request(cont, req_params)
        del req
        del cont
Пример #27
0
def test_detached_sign():
    '''
    Второй необязательный параметр `detach` функции CryptMsg.sign_data()`
    управляет режимом подписывания. При вызове со значение `True` функция
    подписи вернет не полное подписанное сообщение, а только подпись, которую
    можно хранить отдельно от подписанных ей данных.
    '''
    ctx = csp.Crypt(
        test_container,
        PROV_GOST,
        0,
        test_provider
    )
    assert ctx
    cs = csp.CertStore(None, b"MY")
    cert = list(cs.find_by_name(test_cn))[0]
    mess = csp.CryptMsg()
    data = mess.sign_data(b'hurblewurble', cert, True)
    assert len(data)
    return data
Пример #28
0
def test_detached_sign2():
    '''
    Класс `Signature` наследует всю функциональность `CryptMsg`, но
    ориентирован на работу с отсоединенными подписями. Поэтому метод
    `Signature.sign_data()` по умолчанию возвращает отсоединенную подпись.
    '''
    ctx = csp.Crypt(
        test_container,
        PROV_GOST,
        0,
        test_provider
    )
    assert ctx
    cs = csp.CertStore(ctx, b"MY")
    cert = list(cs.find_by_name(test_cn))[0]

    # создание новой (пустой) отсоединенной подписи
    sgn = csp.Signature(ctx)

    # подписывание данных экземпляром `Signature` по умолчанию дает
    # отсоединенную подпись.
    data = sgn.sign_data(b'hurblewurble', cert)
    assert len(data)
    return data
Пример #29
0
def test_encrypt_decrypt():
    thumb = get_test_thumb()
    cert = cryptoapi.get_certificate(thumb)
    cs = csp.CertStore(None, b'My')
    certs = []
    for x in ('res1.cer', ):
        certs.append(open(case_path(x), 'rb').read())
    certs.append(cert)
    wrong_thumbs = list(t for t in (hexlify(c.thumbprint()) for c in cs)
                        if t != thumb)

    encrypted_data = cryptoapi.encrypt(certs, msg)
    open('encrypted_data.bin', 'wb').write(encrypted_data)
    assert encrypted_data
    decrypted_data = cryptoapi.decrypt(encrypted_data, thumb)
    assert msg == decrypted_data

    bad_thumbs = []
    for th in wrong_thumbs[:1]:
        try:
            cryptoapi.decrypt(encrypted_data, th)
        except Exception:
            bad_thumbs.append(th)
    assert bad_thumbs == wrong_thumbs[:1]
Пример #30
0
def test_msg_signatures():
    '''

    Поле `CryptMsg.num_signers` содержит количество подписантов сообщения.

    Функция `CryptMsg.get_nth_signer_info(n)` возвращает структуру, уникально
    идентифицирующую сертификат `n`-го подписанта. По ней можно получить
    сертификат подписанта, либо из хранилища в сообщении, либо из системного
    хранилища.  Для этого служит функция `CertStore.get_cert_by_info()`. Если
    сертификата нет в хранилище, функция возвращает `None`.

    Полученный таким образом сертификат `c` можно использовать для проверки
    подписи под сообщением с помощью функции `CryptMsg.verify_cert(c)`. Функция
    возвращает `True`, если для данного сертификата соответствующая ему подпись
    верна.

    Для упрощения обработки сертификатов, функция `CryptMsg.signer_certs()`
    перечисляет сертификаты всех подписантов сообщения.

    '''
    ctx = csp.Crypt(
        b'',
        PROV_GOST,
        csp.CRYPT_VERIFYCONTEXT,
        test_provider
    )
    testdata = test_sign_data()
    # testdata = open('tests/logical.cms', 'rb').read()

    # загрузка сообщения из блоба данных
    msg = csp.CryptMsg(testdata, ctx)
    del testdata
    # сведения о раскодированном сообщении
    print(msg.num_signers())
    print(len(msg.get_data()))
    # TODO переделать тесты ниже
    return

    # Идентификационная информация для 1-го подписанта.
    psi = msg.get_nth_signer_info(0)
    assert psi
    my = csp.CertStore(msg)
    sys_my = csp.CertStore(None, "MY")

    # Из сообщения можно извлечь сертификат по этой информации
    verify_cert = my.get_cert_by_info(psi)
    t1 = verify_cert.thumbprint()
    verify_cert = my.get_cert_by_info(psi)

    # Сертификат можно извлечь так же из системного хранилища, если он там
    # есть.
    same_cert = sys_my.get_cert_by_info(psi)
    t2 = same_cert.thumbprint()
    assert t1 == t2

    # разнообразные проверки подписей через сертификаты
    print(verify_cert.name())
    assert msg.verify_cert(verify_cert)
    ns = list(c.name() for c in msg.signer_certs())
    assert len(ns)
    cs = list(csp.CertStore(msg))
    print([(msg.verify_cert(x), x.name()) for x in cs])
    assert all(msg.verify_cert(c) for c in cs)