Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't import cryptography generated pkcs12 into macos keychain #7293

Closed
ojii opened this issue May 31, 2022 · 12 comments · Fixed by #7560
Closed

Can't import cryptography generated pkcs12 into macos keychain #7293

ojii opened this issue May 31, 2022 · 12 comments · Fixed by #7560

Comments

@ojii
Copy link

ojii commented May 31, 2022

Versions:

  • Python: 3.10.1
  • cryptography: 37.0.2
  • cffi: 1.15.0

Cryptography installed with poetry 1.2.0b1

I'm trying to create a self-signed certificate with cryptography, which mostly works, but it fails to import to macos (12.1) keychain. If I export the same certificate & private key as a chained PEM file and then use the openssl command line tool to convert it into a p12, I can successfully import it.

This is the code I use to try to export the p12 using cryptography:

def export(path: Path, cert: x509.Certificate, key: rsa.RSAPrivateKeyWithSerialization, password: bytes):
    with path.open('wb') as fobj:
        fobj.write(
            pkcs12.serialize_key_and_certificates(
                name=None,
                cas=None,
                key=key,
                cert=cert,
                encryption_algorithm=serialization.BestAvailableEncryption(password),
            )
        )

However, if instead I do this, macos is happy to import it:

def export(
    path: Path,
    cert: x509.Certificate,
    key: rsa.RSAPrivateKeyWithSerialization,
    password: bytes,
):
    with path.with_suffix(".pem").open("wb") as fobj:
        fobj.write(
            key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.BestAvailableEncryption(password),
            )
        )
        fobj.write(cert.public_bytes(encoding=serialization.Encoding.PEM))
    subprocess.check_call(
        [
            "openssl",
            "pkc12",
            "-export",
            "-in",
            str(path.with_suffix(".pem")),
            "-passin",
            f"pass:{password.decode()}",
            "-out",
            str(path),
            "-passout",
            f"pass:{password.decode()}",
        ]
    )

Am I using serialize_key_and_certificates wrong?

@reaperhulk
Copy link
Member

reaperhulk commented May 31, 2022

What happens if you try this using 36.0.2? I wonder if this is related to #7043 (comment)

@ojii
Copy link
Author

ojii commented Jun 1, 2022

What happens if you try this using 36.0.2? I wonder if this is related to #7043 (comment)

with 36.0.2 it imports just fine.

@reaperhulk reaperhulk added the bugs label Jun 1, 2022
@reaperhulk reaperhulk added this to the Thirty Eighth Release milestone Jun 1, 2022
@reaperhulk
Copy link
Member

Okay, this looks like another manifestation of the OpenSSL 3 transition. Tagging this as a bug we need to get resolved for 38.

@fochoao-o

This comment was marked as spam.

@fochoao-o

This comment was marked as spam.

@alex
Copy link
Member

alex commented Jun 3, 2022

We should figure out why these aren't loading in macOS, and figure out if there's some action we should be pushing Apple to take -- e.g. are they rejecting valid PKCS#12 files?

@TotallyNotASecret
Copy link

@alex I don't think the PKCS#12 files are valid, because the same thing also happened to me with some Windows machines.

@alex
Copy link
Member

alex commented Jun 21, 2022

Unfortunately that's not sufficient to say whether they're valid. Different vendors may have the same bug, or implement the same limited set of OIDs, so we really need an analytic inquiry into the cause of the incompatibility.

@jobec
Copy link

jobec commented Jun 22, 2022

#7043 has some openssl commands to troubleshoot those PKCS#12 files.

If a recent version of openSSL can't read them, I think you can be confident that it's a invalid file.

Most likely MacOS has the same issue as windows, where it doesn't support AES256 as encryption for the PKCS#12 file.
On windows 2016 and older, it must be 3DES with SHA1 MAC or it won't work.

@TotallyNotASecret
Copy link

At least for me OpenSSL can read the files.

@jobec
Copy link

jobec commented Jun 24, 2022

And what's the output from command below?

openssl pkcs12 -noout -info -in some.pfx

With a OpenSSL v3, try converting the PFX to 3DES + SHA1 MAC. Does that work?

openssl pkcs12 -in some.pfx -out temp.pem -nodes
openssl pkcs12 -export -in temp.pem -out legacy_3DES.pfx -macalg SHA1 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES
del /F /Q temp.pem
openssl pkcs12 -noout -info -in legacy_3DES.pfx

@schwabe
Copy link

schwabe commented Jul 29, 2022

So I did some testing/work on this and the same seems to be true for Android as well. I can import pkcs12 when I use SHA1 as macalg but it breaks as soon as I change it to SHA256:

openssl3  pkcs12 -passout pass:test123 -export -in etestcerts.pem -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha1 -out etest-ossl3-3des-sha1.p12` 

works

openssl3  pkcs12 -passout pass:test123 -export -in etestcerts.pem -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha256 -out etest-ossl3-3des-sha1.p12`

is broken.

Digging into the OpenSSL source itself suggests that the macalg function is calling

if (!PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd)) {`

with macmd being the EVP_MD that is the one specified by the -macalg option. The function seems to be first appeared in OpenSSL 3.0.

schwabe added a commit to schwabe/cryptography that referenced this issue Jul 29, 2022
schwabe added a commit to schwabe/cryptography that referenced this issue Jul 30, 2022
schwabe added a commit to schwabe/cryptography that referenced this issue Aug 9, 2022
 pyca#7293)

No tests for PKCS12CompatibilityEncryption for other functions taking
KeySerializationEncryption classes, as the DummyKeySerializationEncryption
tests already check for a proper error in this case.
schwabe added a commit to schwabe/cryptography that referenced this issue Aug 17, 2022
schwabe added a commit to schwabe/cryptography that referenced this issue Aug 17, 2022
 pyca#7293)

No tests for PKCS12CompatibilityEncryption for other functions taking
KeySerializationEncryption classes, as the DummyKeySerializationEncryption
tests already check for a proper error in this case.
@alex alex closed this as completed in #7560 Sep 5, 2022
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 5, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Development

Successfully merging a pull request may close this issue.

7 participants