Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 2c8b7911

Přidáno uživatelem Stanislav Král před téměř 4 roky(ů)

Re #8708 - Implemented a new method in the CryptographyService that allows the caller to create a PKCS12 identity of a certificate and it's chain of trust

Covered the new method with unit tests.

Zobrazit rozdíly:

src/services/cryptography.py
2 2
import subprocess
3 3
import time
4 4
import random
5
from typing import List
5 6

  
6 7
from src.constants import CRL_CONFIG
7 8
from src.model.certificate import Certificate
......
411 412

  
412 413
        # openssl ca requires the .srl file to exists, therefore a dummy, unused file is created
413 414
        with TemporaryFile("serial.srl", "0") as serial_file, \
414
             TemporaryFile("crl.conf", CRL_CONFIG % (index_file_path, serial_file)) as config_file, \
415
             TemporaryFile("certificate.pem", cert.pem_data) as cert_file, \
416
             TemporaryFile("private_key.pem", key.private_key) as key_file:
417

  
415
                TemporaryFile("crl.conf", CRL_CONFIG % (index_file_path, serial_file)) as config_file, \
416
                TemporaryFile("certificate.pem", cert.pem_data) as cert_file, \
417
                TemporaryFile("private_key.pem", key.private_key) as key_file:
418 418
            args = ["ca", "-config", config_file, "-gencrl", "-keyfile", key_file, "-cert", cert_file, "-outdir", "."]
419 419

  
420 420
            if key.password is not None and key.password != "":
......
437 437
        Logger.debug("Function launched.")
438 438

  
439 439
        with TemporaryFile("certificate.pem", cert.pem_data) as ca_certificate, \
440
             TemporaryFile("private_key.pem", key.private_key) as key_file, \
441
             TemporaryFile("request.der", der_ocsp_request) as request_file:
442

  
440
                TemporaryFile("private_key.pem", key.private_key) as key_file, \
441
                TemporaryFile("request.der", der_ocsp_request) as request_file:
443 442
            args = ["ocsp", "-index", index_path, "-CA", ca_certificate, "-rsigner", ca_certificate, "-rkey", key_file,
444 443
                    "-reqin", request_file, "-respout", "-"]
445 444

  
......
448 447

  
449 448
            return self.__run_for_output(args)
450 449

  
450
    def generate_pkcs_identity(self, cert_pem: str, cert_key_pem: str, identity_name: str, identity_passphrase: str,
451
                               chain_of_trust_pems: List[str], cert_key_passphrase: str = None):
452
        """
453
        Generates a PKCS12 identity of the given child certificate while including the given chain of trust.
454

  
455
        :param cert_pem: PEM of the certificate whose identity should be created
456
        :param cert_key_pem: PEM of the private key used to sign the certificate whose identity should be created
457
        :param identity_name: the name to be given to the identity created
458
        :param chain_of_trust_pems: list of PEMs representing certificates present in the chain of trust of the certificate
459
        whose identity should be created
460
        :param identity_passphrase: passphrase to be used when encrypting the identity
461
        :param cert_key_passphrase: passphrase of the key used to sign the certificate whose identity should be created
462
        :return: byte array containing the generated identity
463
        """
464
        with TemporaryFile("cert_key.pem", cert_key_pem) as cert_key_pem_file:
465
            args = ["pkcs12", "-export", "-name", identity_name, "-in", "-", "-inkey", cert_key_pem_file, "-CAfile",
466
                    "-", "-passout", f"pass:{identity_passphrase}", "-passin", f"pass:{cert_key_passphrase}"]
467
            return self.__run_for_output(args,
468
                                         proc_input=bytes(cert_pem + "".join(chain_of_trust_pems),
469
                                                          encoding="utf-8"))
470

  
451 471

  
452 472
class CryptographyException(Exception):
453 473

  
tests/unit_tests/services/cryptography/generate_pkcs_identity_test.py
1
import subprocess
2

  
3
import pytest
4

  
5
from src.model.subject import Subject
6
from src.services.cryptography import CryptographyException
7

  
8

  
9
def test_generate_pkcs_identity(service):
10
    root_key = service.create_private_key()
11
    root_cert = service.create_sscrt(Subject(common_name="Foo"), root_key)
12

  
13
    inter_key = service.create_private_key()
14
    inter_cert = service.create_crt(Subject(common_name="Bar"), inter_key, root_cert, root_key)
15

  
16
    child_key = service.create_private_key()
17
    child_cert = service.create_crt(Subject(common_name="Baz"), child_key, inter_cert, inter_key)
18

  
19
    pkcs = service.generate_pkcs_identity(child_cert, child_key, "Baz Pkcs", "secret_pass",
20
                                          "".join([root_cert, inter_cert]))
21

  
22
    # print out the pkcs store in order to be able to check it
23
    pkcs_info = subprocess.check_output(
24
        ["openssl", "pkcs12", "-info", "-in", "-", "-nodes", "-passin", "pass:secret_pass"],
25
        input=pkcs,
26
        stderr=subprocess.STDOUT).decode()
27

  
28
    assert child_cert in pkcs_info
29

  
30
    assert "-----BEGIN PRIVATE KEY-----" in pkcs_info
31
    assert root_cert in pkcs_info
32
    assert inter_cert in pkcs_info
33

  
34

  
35
def test_generate_pkcs_identity_encrypted_key(service):
36
    root_key = service.create_private_key()
37
    root_cert = service.create_sscrt(Subject(common_name="Foo"), root_key)
38

  
39
    inter_key = service.create_private_key()
40
    inter_cert = service.create_crt(Subject(common_name="Bar"), inter_key, root_cert, root_key)
41

  
42
    # protect the child key with a passphrase
43
    child_key_passphrase = "keypass"
44
    child_key = service.create_private_key(passphrase=child_key_passphrase)
45
    child_cert = service.create_crt(Subject(common_name="Baz"), child_key, inter_cert, inter_key, child_key_passphrase)
46

  
47
    pkcs = service.generate_pkcs_identity(child_cert, child_key, "Baz Pkcs", "secret_pass",
48
                                          "".join([root_cert, inter_cert]),
49
                                          cert_key_passphrase=child_key_passphrase)
50

  
51
    # print out the pkcs store in order to be able to check it
52
    pkcs_info = subprocess.check_output(
53
        ["openssl", "pkcs12", "-info", "-in", "-", "-nodes", "-passin", "pass:secret_pass"],
54
        input=pkcs,
55
        stderr=subprocess.STDOUT).decode()
56

  
57
    assert child_cert in pkcs_info
58

  
59
    assert "-----BEGIN PRIVATE KEY-----" in pkcs_info
60
    assert root_cert in pkcs_info
61
    assert inter_cert in pkcs_info
62

  
63

  
64
def test_generate_pkcs_identity_encrypted_key_passphrase_not_provided(service):
65
    root_key = service.create_private_key()
66
    root_cert = service.create_sscrt(Subject(common_name="Foo"), root_key)
67

  
68
    inter_key = service.create_private_key()
69
    inter_cert = service.create_crt(Subject(common_name="Bar"), inter_key, root_cert, root_key)
70

  
71
    # protect the child key with a passphrase
72
    child_key_passphrase = "keypass"
73
    child_key = service.create_private_key(passphrase=child_key_passphrase)
74
    child_cert = service.create_crt(Subject(common_name="Baz"), child_key, inter_cert, inter_key, child_key_passphrase)
75

  
76
    with pytest.raises(CryptographyException):
77
        service.generate_pkcs_identity(child_cert, child_key, "Baz Pkcs", "secret_pass",
78
                                       "".join([root_cert, inter_cert]))
79

  
80

  
81
def test_generate_pkcs_identity_encrypted_key_incorrect_passphrase(service):
82
    root_key = service.create_private_key()
83
    root_cert = service.create_sscrt(Subject(common_name="Foo"), root_key)
84

  
85
    inter_key = service.create_private_key()
86
    inter_cert = service.create_crt(Subject(common_name="Bar"), inter_key, root_cert, root_key)
87

  
88
    # protect the child key with a passphrase
89
    child_key_passphrase = "keypass"
90
    child_key = service.create_private_key(passphrase=child_key_passphrase)
91
    child_cert = service.create_crt(Subject(common_name="Baz"), child_key, inter_cert, inter_key, child_key_passphrase)
92

  
93
    with pytest.raises(CryptographyException):
94
        service.generate_pkcs_identity(child_cert, child_key, "Baz Pkcs", "secret_pass",
95
                                       "".join([root_cert, inter_cert]), cert_key_passphrase="passkey")

Také k dispozici: Unified diff