apple / swift-certificates

An implementation of X.509 for Swift
https://swiftpackageindex.com/apple/swift-certificates/main/documentation/x509
Apache License 2.0
220 stars 53 forks source link

New API Proposal: PKCS#12 Support #114

Open Craz1k0ek opened 1 year ago

Craz1k0ek commented 1 year ago

New API Proposal: PKCS#12 Support

Motivation:

Thinking of X.509, certificates and keys and ways to transport these at once, one must have ran into the PKCS#12 standard. It's an archive file format used for storing all kinds of cryptography objects. It's often used to, but not limited to:

Importance:

A quick search reveals that there are some existing server side/native implementations that already have some form of PKCS#12 occurrence already (swift-nio-ssl, Uniform Type Idnetifiers, ...) and I feel like this certificate library is a good fit to have some form of PKCS#12 support too, which may be limited to combining a private key and a related certificate into a container, or combining the certificate chain into a container.

Lukasa commented 1 year ago

I'm generally a bit reluctant to get too far down into supporting PKCS#12. It's a very complex and general format, that also has a lot of legacy baggage. For example, PBES1 is typically used to protect the contents, a scheme that uses either DES or RC2 as the bulk cipher. Neither of those are good choices in 2023, and we don't have Swift API for them. PBES2 is conceptually more broadly useful, but still requires a bunch of new primitives in swift-crypto that represent poor cryptographic choices.

In general, I think I'd prefer to allow other tools to produce PKCS#12 files. There are a wide range of API surfaces for achieving this outcome on a number of platforms, and it would probably be better to delegate to those APIs.

Craz1k0ek commented 1 year ago

Fair point about it being an interesting format. As for the crypto behind it, it is already implemented at OpenSSL/BoringSSL, so I believe we should somehow be able to map those implementations to Swift. If you do feel that PBES1/PBES2 is insufficient, there's also the option to not provide any password (seems more insufficient); the last one would mean that someone can just encrypt the file using the contemporary cryptographic primitives.

and we don't have Swift API for them

This should never be an argument to not implement something. Anything can be made! 💪🏼

but still requires a bunch of new primitives in swift-crypto that represent poor cryptographic choices

We do have an Insecure enum, isn't that just for this? What about making it hidden/obfuscated like the _RSA enum?

There are a wide range of API surfaces for achieving this outcome on a number of platforms, and it would probably be better to delegate to those APIs

In the meantime, can you point me at such tools, preferably in Swift/Objective-C/iOS/macOS?

Lukasa commented 1 year ago

As for the crypto behind it, it is already implemented at OpenSSL/BoringSSL, so I believe we should somehow be able to map those implementations to Swift.

Sure, that's very do-able. The question is much more about whether we should do it. The trade-off that CryptoKit (and by extension Crypto) have tried to make has been about being opinionated. Where possible, we don't want to allow sharp edges that make it too attractive or easy to use primitives that are no longer up to the task.

You're right that the Insecure enum is related to this need, but it's worth examining what's actually in it. It contains two things, both hash functions: MD5 and SHA1. Both of these have a number of perfectly safe uses: HMAC-MD5 remains safe, albeit suboptimal.

DES, RC2, and 3DES are in a very different boat. Bringing these algorithms, which are all superseded by stronger and better alternatives, into something like Swift Crypto is really quite substantially risky.

A good suggestion for how to manage this would be to consider implementing the PKCS#12 support in a separate package. This package could depend on swift-certificates (for certs), swift-asn1 (for the PKCS#12 DER), and then bring its own implementations of the encryption primitives. That allows users who require PKCS#12 to obtain it, without pushing the weaker crypto primitives into the core Swift cryptography libraries.

In the meantime, can you point me at such tools, preferably in Swift/Objective-C/iOS/macOS?

The easiest shortcut tool is swift-nio-ssl: adding support to that library to be able to produce PKCS#12 files is a good first step. The OpenSSL command line tool is also capable of achieving this. So can Keychain Access on macOS.