def test_export_import_pubkey(): ''' Функция `Crypt.get_key(keytype=csp.AT_SIGNATURE)` возвращает одну из двух пар открытый/закрытый ключ, связанных с контекстом. Необязательный параметр `keytype` по умолчанию обеспечивает извлечение ключей подписи. Может также принимать значение `csp.AT_KEYEXCHANGE`, для извлечения ключей обмена. Результатом функции является либо экземпляр класса `Key()` либо `None`, если хранилище не содержит ключей. Функция `Key.encode(cryptkey=None)` экспортирует ключ во внутренний бинарный формат для передачи по каналам данных. Необязательный параметр `cryptkey` задает открытый ключ получателя. При его использовании экспортируется закрытая половина ключа в зашифрованном для получателя виде. Без этого параметра экспортируется незашифрованный открытый ключ. Функция `Crypt.import_key(k, decrypt)` связывает ключ `k` с контекстом криптопровайдера. Параметр `k` содержит блоб для передачи ключа во внутреннем формате. Необязательный второй параметр `decrypt` задает объект `Key` для расшифровки закрытого ключа. ''' context = csp.Crypt(test_container, PROV_GOST, 0, test_provider) recipient = csp.Crypt(b'', PROV_GOST, csp.CRYPT_VERIFYCONTEXT, test_provider) sk = context.get_key() assert sk pk = recipient.import_key(sk.encode()) assert pk
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
def test_store_key(): context = csp.Crypt(test_container, PROV_GOST, 0, test_provider) key = context.get_key() certdata = test_extract_cert() newc = csp.Cert(certdata) key.store_cert(newc) assert key.extract_cert() == certdata
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())
def test_context_not_found(): ctx = csp.Crypt( b"some_wrong_ctx", PROV_GOST, csp.CRYPT_SILENT, test_provider, ) assert not ctx
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
def main(): global ctxname ctx = csp.Crypt(ctxname, csp.PROV_GOST_2012_256, 0 | csp.CRYPT_SILENT, provider) if not ctx: print('Container', ctxname, 'not found!') return print(ctx.name()) print(ctx.prov_name()) print(ctx.uniq_name()) print(ctx.prov_type())
def test_derive_key(): ctx = csp.Crypt( b'', PROV_GOST, csp.CRYPT_VERIFYCONTEXT, test_provider ) data = b'1234' hash1 = csp.Hash(ctx, data) key1 = hash1.derive_key() return key1
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
def test_hash_hmac(): key = test_derive_key() ctx = csp.Crypt( b'', PROV_GOST, csp.CRYPT_VERIFYCONTEXT, test_provider ) data = b'The quick brown fox jumps over the lazy dog' hash1 = csp.Hash(ctx, data, key, 0) digest_str = hexlify(hash1.digest()) print(digest_str) assert digest_str == b'3e7dea7f2384b6c5a3d0e24aaa29c05e89ddd762145030ec22c71a6db8b2c1f4'
def test_context_named_keystore(): ''' Подключение к именованному контейнеру. Если контейнер с данным именем не найден, будет возвращено `None`. ''' context = csp.Crypt( test_container, PROV_GOST, 0, test_provider, ) assert context return context
def test_hash_digest_string(): ctx = csp.Crypt( b'', PROV_GOST, csp.CRYPT_VERIFYCONTEXT, test_provider ) data = b'The quick brown fox jumps over the lazy dog' length = 0 if test_cn.endswith(b'2012') else 2001 hash1 = csp.Hash(ctx, data, length) digest_str = hexlify(hash1.digest()) print(digest_str, length) if length == 2001: assert digest_str == b'9004294a361a508c586fe53d1f1b02746765e71b765472786e4770d565830a76' return assert digest_str == b'3e7dea7f2384b6c5a3d0e24aaa29c05e89ddd762145030ec22c71a6db8b2c1f4'
def test_hash_digest_empty(): ctx = csp.Crypt( b'', PROV_GOST, csp.CRYPT_VERIFYCONTEXT, test_provider ) data = b'' length = 0 if test_cn.endswith(b'2012') else 2001 hash1 = csp.Hash(ctx, data, length) digest_str = hexlify(hash1.digest()) print(digest_str, length) if length == 2001: assert digest_str == b'981e5f3ca30c841487830f84fb433e13ac1101569b9c13584ac483234cd656c0' return assert digest_str == b'3f539a213e97c802cc229d474c6aa32a825a360b2a933a949fd925208d9ce1bb'
def test_context_simple(): ''' Контест создается функцией `Crypt()`. Первым параметром передается строка-имя контейнера ключей. Второй параметр -- тип провайдера, третий -- флаги. Контейнер без имени является контейнером пользователя по умолчанию. Результатом функции является экземпляр класса `Crypt()`. Если именованный контейнер не найден, бросается исключение `ValueError`. ''' context = csp.Crypt( b'', PROV_GOST, csp.CRYPT_VERIFYCONTEXT, test_provider ) assert context return context
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
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
def test_hash_digest_random(): ''' Test Hash() Объект Hash может инициализироваться данными из байтовой строки или быть пустым. Метод `Hash.update()` добавляет данные из байтовой строки `s` к хэшу. Метод `Hash.digest()` возвращает хэш в виде байтовой строки. После вызова digest() добавлять данные больше нельзя. ''' ctx = csp.Crypt( b'', PROV_GOST, csp.CRYPT_VERIFYCONTEXT, test_provider ) data = os.urandom(1024) length = 0 if test_cn.endswith(b'2012') else 2001 hash1 = csp.Hash(ctx, data, length) hash2 = csp.Hash(ctx, length) hash2.update(data) digest1 = hash1.digest() digest2 = hash2.digest() print(hexlify(digest1), hexlify(digest2)) assert digest1 == digest2
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
def test_csp_info(): context = csp.Crypt(test_container, PROV_GOST, 0, test_provider) info = csp.CSPInfo(context) assert info assert info.version() assert len(info.bytes())
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)