Esempio n. 1
0
 def test_sign_no_data(self):
     cert, key = _load_cert_key()
     builder = pkcs7.PKCS7SignatureBuilder().add_signer(
         cert, key, hashes.SHA256()
     )
     with pytest.raises(ValueError):
         builder.sign(serialization.Encoding.SMIME, [])
Esempio n. 2
0
    def test_sign_text(self, backend):
        data = b"hello world"
        cert, key = _load_cert_key()
        builder = (pkcs7.PKCS7SignatureBuilder().set_data(data).add_signer(
            cert, key, hashes.SHA256()))

        options = [
            pkcs7.PKCS7Options.Text,
            pkcs7.PKCS7Options.DetachedSignature,
        ]
        sig_pem = builder.sign(serialization.Encoding.SMIME, options)
        # The text option adds text/plain headers to the S/MIME message
        # These headers are only relevant in SMIME mode, not binary, which is
        # just the PKCS7 structure itself.
        assert b"text/plain" in sig_pem
        # When passing the Text option the header is prepended so the actual
        # signed data is this.
        signed_data = b"Content-Type: text/plain\r\n\r\nhello world"
        _pkcs7_verify(
            serialization.Encoding.SMIME,
            sig_pem,
            signed_data,
            [cert],
            options,
            backend,
        )
Esempio n. 3
0
 def test_sign_invalid_options_text_no_detached(self, backend):
     cert, key = _load_cert_key()
     builder = (pkcs7.PKCS7SignatureBuilder().set_data(b"test").add_signer(
         cert, key, hashes.SHA256()))
     options = [pkcs7.PKCS7Options.Text]
     with pytest.raises(ValueError):
         builder.sign(serialization.Encoding.SMIME, options)
Esempio n. 4
0
 def test_sign_binary(self, backend):
     data = b"hello\nworld"
     cert, key = _load_cert_key()
     builder = (pkcs7.PKCS7SignatureBuilder().set_data(data).add_signer(
         cert, key, hashes.SHA256()))
     options: typing.List[pkcs7.PKCS7Options] = []
     sig_no_binary = builder.sign(serialization.Encoding.DER, options)
     sig_binary = builder.sign(serialization.Encoding.DER,
                               [pkcs7.PKCS7Options.Binary])
     # Binary prevents translation of LF to CR+LF (SMIME canonical form)
     # so data should not be present in sig_no_binary, but should be present
     # in sig_binary
     assert data not in sig_no_binary
     _pkcs7_verify(
         serialization.Encoding.DER,
         sig_no_binary,
         None,
         [cert],
         options,
         backend,
     )
     assert data in sig_binary
     _pkcs7_verify(
         serialization.Encoding.DER,
         sig_binary,
         None,
         [cert],
         options,
         backend,
     )
Esempio n. 5
0
 def test_multiple_signers_different_hash_algs(self, backend):
     data = b"hello world"
     cert, key = _load_cert_key()
     rsa_key = load_vectors_from_file(
         os.path.join("x509", "custom", "ca", "rsa_key.pem"),
         lambda pemfile: serialization.load_pem_private_key(
             pemfile.read(), None),
         mode="rb",
     )
     rsa_cert = load_vectors_from_file(
         os.path.join("x509", "custom", "ca", "rsa_ca.pem"),
         loader=lambda pemfile: x509.load_pem_x509_certificate(pemfile.read(
         )),
         mode="rb",
     )
     assert isinstance(rsa_key, rsa.RSAPrivateKey)
     builder = (pkcs7.PKCS7SignatureBuilder().set_data(data).add_signer(
         cert, key, hashes.SHA384()).add_signer(rsa_cert, rsa_key,
                                                hashes.SHA512()))
     options: typing.List[pkcs7.PKCS7Options] = []
     sig = builder.sign(serialization.Encoding.DER, options)
     # There should be two SHA384 and two SHA512 OIDs in this structure
     assert sig.count(b"\x06\t`\x86H\x01e\x03\x04\x02\x02") == 2
     assert sig.count(b"\x06\t`\x86H\x01e\x03\x04\x02\x03") == 2
     _pkcs7_verify(
         serialization.Encoding.DER,
         sig,
         None,
         [cert, rsa_cert],
         options,
         backend,
     )
Esempio n. 6
0
    def test_sign_no_attributes(self, backend):
        data = b"hello world"
        cert, key = _load_cert_key()
        builder = (
            pkcs7.PKCS7SignatureBuilder()
            .set_data(data)
            .add_signer(cert, key, hashes.SHA256())
        )

        options = [pkcs7.PKCS7Options.NoAttributes]
        sig_binary = builder.sign(serialization.Encoding.DER, options)
        # NoAttributes removes all authenticated attributes, so we shouldn't
        # find SMIMECapabilities or signingTime.

        # 1.2.840.113549.1.9.15 SMIMECapabilities as an ASN.1 DER encoded OID
        assert b"\x06\t*\x86H\x86\xf7\r\x01\t\x0f" not in sig_binary
        # 1.2.840.113549.1.9.5 signingTime as an ASN.1 DER encoded OID
        assert b"\x06\t*\x86H\x86\xf7\r\x01\t\x05" not in sig_binary
        _pkcs7_verify(
            serialization.Encoding.DER,
            sig_binary,
            None,
            [cert],
            options,
            backend,
        )
Esempio n. 7
0
 def test_unsupported_key_type(self, backend):
     cert, _ = _load_cert_key()
     key = ed25519.Ed25519PrivateKey.generate()
     with pytest.raises(TypeError):
         pkcs7.PKCS7SignatureBuilder().add_signer(
             cert, key, hashes.SHA256()
         )
Esempio n. 8
0
    def test_smime_sign_detached(self, backend):
        data = b"hello world"
        cert, key = _load_cert_key()
        options = [pkcs7.PKCS7Options.DetachedSignature]
        builder = (pkcs7.PKCS7SignatureBuilder().set_data(data).add_signer(
            cert, key, hashes.SHA256()))

        sig = builder.sign(serialization.Encoding.SMIME, options)
        sig_binary = builder.sign(serialization.Encoding.DER, options)
        # We don't have a generic ASN.1 parser available to us so we instead
        # will assert on specific byte sequences being present based on the
        # parameters chosen above.
        assert b"sha-256" in sig
        # Detached signature means that the signed data is *not* embedded into
        # the PKCS7 structure itself, but is present in the SMIME serialization
        # as a separate section before the PKCS7 data. So we should expect to
        # have data in sig but not in sig_binary
        assert data in sig
        _pkcs7_verify(serialization.Encoding.SMIME, sig, data, [cert], options,
                      backend)
        assert data not in sig_binary
        _pkcs7_verify(
            serialization.Encoding.DER,
            sig_binary,
            data,
            [cert],
            options,
            backend,
        )
Esempio n. 9
0
    def test_sign_no_capabilities(self, backend):
        data = b"hello world"
        cert, key = _load_cert_key()
        builder = (pkcs7.PKCS7SignatureBuilder().set_data(data).add_signer(
            cert, key, hashes.SHA256()))

        options = [pkcs7.PKCS7Options.NoCapabilities]
        sig_binary = builder.sign(serialization.Encoding.DER, options)
        # NoCapabilities removes the SMIMECapabilities attribute from the
        # PKCS7 structure. This is an ASN.1 sequence with the
        # OID 1.2.840.113549.1.9.15. It does NOT remove all authenticated
        # attributes, so we verify that by looking for the signingTime OID.

        # 1.2.840.113549.1.9.15 SMIMECapabilities as an ASN.1 DER encoded OID
        assert b"\x06\t*\x86H\x86\xf7\r\x01\t\x0f" not in sig_binary
        # 1.2.840.113549.1.9.5 signingTime as an ASN.1 DER encoded OID
        assert b"\x06\t*\x86H\x86\xf7\r\x01\t\x05" in sig_binary
        _pkcs7_verify(
            serialization.Encoding.DER,
            sig_binary,
            None,
            [cert],
            options,
            backend,
        )
Esempio n. 10
0
 def test_not_a_cert(self, backend):
     cert, key = _load_cert_key()
     with pytest.raises(TypeError):
         pkcs7.PKCS7SignatureBuilder().add_signer(
             b"notacert",
             key,
             hashes.SHA256()  # type: ignore[arg-type]
         )
Esempio n. 11
0
 def test_unsupported_hash_alg(self, backend):
     cert, key = _load_cert_key()
     with pytest.raises(TypeError):
         pkcs7.PKCS7SignatureBuilder().add_signer(
             cert,
             key,
             hashes.SHA512_256()  # type: ignore[arg-type]
         )
Esempio n. 12
0
 def test_sign_invalid_options(self, backend):
     cert, key = _load_cert_key()
     builder = (pkcs7.PKCS7SignatureBuilder().set_data(b"test").add_signer(
         cert, key, hashes.SHA256()))
     with pytest.raises(ValueError):
         builder.sign(
             serialization.Encoding.SMIME,
             [b"invalid"],  # type: ignore[list-item]
         )
Esempio n. 13
0
    def test_sign_byteslike(self, backend):
        data = bytearray(b"hello world")
        cert, key = _load_cert_key()
        options = [pkcs7.PKCS7Options.DetachedSignature]
        builder = (pkcs7.PKCS7SignatureBuilder().set_data(data).add_signer(
            cert, key, hashes.SHA256()))

        sig = builder.sign(serialization.Encoding.SMIME, options)
        assert bytes(data) in sig
Esempio n. 14
0
 def test_sign_invalid_encoding(self):
     cert, key = _load_cert_key()
     builder = (
         pkcs7.PKCS7SignatureBuilder()
         .set_data(b"test")
         .add_signer(cert, key, hashes.SHA256())
     )
     with pytest.raises(ValueError):
         builder.sign(serialization.Encoding.Raw, [])
Esempio n. 15
0
 def test_sign_alternate_digests_detached(self, hash_alg, expected_value):
     data = b"hello world"
     cert, key = _load_cert_key()
     builder = (pkcs7.PKCS7SignatureBuilder().set_data(data).add_signer(
         cert, key, hash_alg))
     options = [pkcs7.PKCS7Options.DetachedSignature]
     sig = builder.sign(serialization.Encoding.SMIME, options)
     # When in detached signature mode the hash algorithm is stored as a
     # byte string like "sha-384".
     assert expected_value in sig
Esempio n. 16
0
 def _sign_payload(self, temp_dir: str, cert: str, key: str) -> bytes:
     """ signs the payload with one signer """
     sb = pkcs7.PKCS7SignatureBuilder(Path(temp_dir, self.PAYLOAD_FILENAME).read_bytes())\
         .add_signer(certs.decode_certificate(cert),
                     keys.decode_key(key),
                     hashes.SHA512())
     return sb.sign(serialization.Encoding.DER, [
         pkcs7.PKCS7Options.NoCerts, pkcs7.PKCS7Options.NoCapabilities,
         pkcs7.PKCS7Options.Binary
     ])
Esempio n. 17
0
 def test_sign_invalid_options_no_attrs_and_no_caps(self, backend):
     cert, key = _load_cert_key()
     builder = (pkcs7.PKCS7SignatureBuilder().set_data(b"test").add_signer(
         cert, key, hashes.SHA256()))
     options = [
         pkcs7.PKCS7Options.NoAttributes,
         pkcs7.PKCS7Options.NoCapabilities,
     ]
     with pytest.raises(ValueError):
         builder.sign(serialization.Encoding.SMIME, options)
Esempio n. 18
0
 def test_sign_alternate_digests_der(self, hash_alg, expected_value,
                                     backend):
     data = b"hello world"
     cert, key = _load_cert_key()
     builder = (pkcs7.PKCS7SignatureBuilder().set_data(data).add_signer(
         cert, key, hash_alg))
     options: typing.List[pkcs7.PKCS7Options] = []
     sig = builder.sign(serialization.Encoding.DER, options)
     assert expected_value in sig
     _pkcs7_verify(serialization.Encoding.DER, sig, None, [cert], options,
                   backend)
Esempio n. 19
0
    def test_sign_no_certs(self, backend):
        data = b"hello world"
        cert, key = _load_cert_key()
        builder = (pkcs7.PKCS7SignatureBuilder().set_data(data).add_signer(
            cert, key, hashes.SHA256()))

        options: typing.List[pkcs7.PKCS7Options] = []
        sig = builder.sign(serialization.Encoding.DER, options)
        assert sig.count(cert.public_bytes(serialization.Encoding.DER)) == 1

        options = [pkcs7.PKCS7Options.NoCerts]
        sig_no = builder.sign(serialization.Encoding.DER, options)
        assert sig_no.count(cert.public_bytes(serialization.Encoding.DER)) == 0
Esempio n. 20
0
    def test_sign_alternate_digests_detached(self, hash_alg, expected_value,
                                             backend):
        if isinstance(hash_alg, hashes.SHA1) and backend._fips_enabled:
            pytest.skip("SHA1 not supported in FIPS mode")

        data = b"hello world"
        cert, key = _load_cert_key()
        builder = (pkcs7.PKCS7SignatureBuilder().set_data(data).add_signer(
            cert, key, hash_alg))
        options = [pkcs7.PKCS7Options.DetachedSignature]
        sig = builder.sign(serialization.Encoding.SMIME, options)
        # When in detached signature mode the hash algorithm is stored as a
        # byte string like "sha-384".
        assert expected_value in sig
Esempio n. 21
0
    def test_sign_alternate_digests_der(self, hash_alg, expected_value,
                                        backend):
        if isinstance(hash_alg, hashes.SHA1) and backend._fips_enabled:
            pytest.skip("SHA1 not supported in FIPS mode")

        data = b"hello world"
        cert, key = _load_cert_key()
        builder = (pkcs7.PKCS7SignatureBuilder().set_data(data).add_signer(
            cert, key, hash_alg))
        options: typing.List[pkcs7.PKCS7Options] = []
        sig = builder.sign(serialization.Encoding.DER, options)
        assert expected_value in sig
        _pkcs7_verify(serialization.Encoding.DER, sig, None, [cert], options,
                      backend)
Esempio n. 22
0
 def test_add_additional_cert(self, backend):
     data = b"hello world"
     cert, key = _load_cert_key()
     rsa_cert = load_vectors_from_file(
         os.path.join("x509", "custom", "ca", "rsa_ca.pem"),
         loader=lambda pemfile: x509.load_pem_x509_certificate(pemfile.read(
         )),
         mode="rb",
     )
     builder = (pkcs7.PKCS7SignatureBuilder().set_data(data).add_signer(
         cert, key, hashes.SHA384()).add_certificate(rsa_cert))
     options: typing.List[pkcs7.PKCS7Options] = []
     sig = builder.sign(serialization.Encoding.DER, options)
     assert (sig.count(rsa_cert.public_bytes(
         serialization.Encoding.DER)) == 1)
Esempio n. 23
0
def sign_data(data: str) -> str:
    with open(config.mobileconfig_key(), "rb") as private_key_file:
        private_key = serialization.load_pem_private_key(
            private_key_file.read(), password=None, backend=None)

    with open(config.mobileconfig_cert(), "rb") as public_cert_file:
        public_cert = x509.load_pem_x509_certificate(public_cert_file.read())

    with open(config.mobileconfig_ca(), "rb") as public_ca_file:
        ca_cert = x509.load_pem_x509_certificate(public_ca_file.read())

    return pkcs7.PKCS7SignatureBuilder().set_data(data).add_signer(
        public_cert, private_key,
        hashes.SHA256()).add_certificate(ca_cert).sign(
            serialization.Encoding.DER, [])
Esempio n. 24
0
    def test_sign_pem(self, backend):
        data = b"hello world"
        cert, key = _load_cert_key()
        options: typing.List[pkcs7.PKCS7Options] = []
        builder = (pkcs7.PKCS7SignatureBuilder().set_data(data).add_signer(
            cert, key, hashes.SHA256()))

        sig = builder.sign(serialization.Encoding.PEM, options)
        _pkcs7_verify(
            serialization.Encoding.PEM,
            sig,
            None,
            [cert],
            options,
            backend,
        )
Esempio n. 25
0
    def test_sign_attached(self, backend):
        data = b"hello world"
        cert, key = _load_cert_key()
        options: typing.List[pkcs7.PKCS7Options] = []
        builder = (pkcs7.PKCS7SignatureBuilder().set_data(data).add_signer(
            cert, key, hashes.SHA256()))

        sig_binary = builder.sign(serialization.Encoding.DER, options)
        # When not passing detached signature the signed data is embedded into
        # the PKCS7 structure itself
        assert data in sig_binary
        _pkcs7_verify(
            serialization.Encoding.DER,
            sig_binary,
            None,
            [cert],
            options,
            backend,
        )
Esempio n. 26
0
    def test_sign_smime_canonicalization(self, backend):
        data = b"hello\nworld"
        cert, key = _load_cert_key()
        builder = (pkcs7.PKCS7SignatureBuilder().set_data(data).add_signer(
            cert, key, hashes.SHA256()))

        options: typing.List[pkcs7.PKCS7Options] = []
        sig_binary = builder.sign(serialization.Encoding.DER, options)
        # LF gets converted to CR+LF (SMIME canonical form)
        # so data should not be present in the sig
        assert data not in sig_binary
        assert b"hello\r\nworld" in sig_binary
        _pkcs7_verify(
            serialization.Encoding.DER,
            sig_binary,
            None,
            [cert],
            options,
            backend,
        )
Esempio n. 27
0
def sign_payload(payload):
    api_settings = settings["api"]
    tls_privkey = api_settings.get("tls_privkey")
    if not tls_privkey:
        logger.error("Could not sign payload: missing tls privkey")
        return payload
    tls_fullchain = api_settings.get("tls_fullchain")
    if not tls_fullchain:
        logger.error("Could not sign payload: missing tls fullchain")
        return payload
    certificates = []
    key = serialization.load_pem_private_key(
        api_settings["tls_privkey"].encode("utf-8"), None)
    head = "-----BEGIN CERTIFICATE-----"
    for tail in api_settings["tls_fullchain"].split(head)[1:]:
        cert_data = (head + tail).encode("utf-8")
        certificates.append(x509.load_pem_x509_certificate(cert_data))
    signature_builder = pkcs7.PKCS7SignatureBuilder().set_data(
        payload).add_signer(certificates.pop(0), key, hashes.SHA256())
    for certificate in certificates:
        signature_builder = signature_builder.add_certificate(certificate)
    return signature_builder.sign(serialization.Encoding.DER,
                                  [pkcs7.PKCS7Options.Binary])
Esempio n. 28
0
 def test_add_additional_cert_not_a_cert(self, backend):
     with pytest.raises(TypeError):
         pkcs7.PKCS7SignatureBuilder().add_certificate(
             b"notacert"  # type: ignore[arg-type]
         )
Esempio n. 29
0
 def test_set_data_twice(self, backend):
     builder = pkcs7.PKCS7SignatureBuilder().set_data(b"test")
     with pytest.raises(ValueError):
         builder.set_data(b"test")
Esempio n. 30
0
 def test_sign_no_signer(self, backend):
     builder = pkcs7.PKCS7SignatureBuilder().set_data(b"test")
     with pytest.raises(ValueError):
         builder.sign(serialization.Encoding.SMIME, [])