Tracking issue for talking about PKCS12 support. PKCS12 v1.1 has been codified in RFC 7292. Unfortunately, PKCS12 is a complex standard with several types nobody really uses and optional features that many (all?) implementations may not support. However, the typical use case for PKCS12 is just cert (possibly with chain) + private key. This seems like a candidate for building a hazmat API that supports everything (although I don't know how much of PKCS12 OpenSSL actually supports) and then a recipes layer API that supports the typical use case.
PKCS12 data is wrapped in a PKCS7 ContentInfo (and DigestInfo in the case of macData) so we probably need to tackle PKCS7 first (see #1621).
I know the command line openssl pkcs12 is pretty full-featured since I used it for generating files to parse. If you went down the path of parsing the structure and then decrypting the contents, you'd need to deal with the PKCS#12 KDF (PKCS12_key_gen_uni) and PBKDF2 (PKCS5_PBKDF2_HMAC). Additionally, you'd need to be able to decrypt RC2, RC4, DES and TripleDES. Many .p12 files created by OS X and Windows tools by default tend to use poor/weak encryption. However, the PKCS#12 v1.1 standard (via the newest version of PKCS#5) does support strong encryption using AES.
When I implemented support for it, I avoided PKCS12_parse() since it dealt with stacks, which heavily use macros, and I only interact with OpenSSL via dlopen. However, since cryptography compiles against OpenSSL, I would imagine you could use it.
If you wanted to go down the route of arbitrary parsing of PKCS#7/CMS, I ended up doing that in Python for more control since my use case required it. Not that I expect that to be a useful route since cryptography is pretty tightly coupled to OpenSSL, but here are some links that someone may find useful:
+1, I have need of PKCS12 functionality in cryptography.
RFE: expose legacy interfaces RC2, PKCS12 KDF
I have a PKCS12 tool (based on pyjks+asn1crypto and using cryptography to do all crypto). The tool converts between pkcs12/jks/bks/PEM with full round-tripping. Currently cryptography doesn't expose RC2 and PKCS12 KDF so I have to reach out to other libraries. (Technically, I also need twofish to support the uber keystore format, but that is outside the scope of this issue.)
API I have in mind:
@utils.register_interface(BlockCipherAlgorithm)
@utils.register_interface(CipherAlgorithm)
class RC2(object):
name = "rc2"
## use RC2 from OpenSSL
## FIXME: need an interface to use EVP_CTRL_SET_RC2_KEY_BITS (aka effective_key_length
## in pycrypto). AES in CTR also uses EVP_CTRL_??? in current backend
@utils.register_interface(KeyDerivationFunction)
class PBKDFPKCS12(object):
def __init__(self, algorithm, length, salt, iterations, backend):
### need OpenSSL's p12_crpt.c:PKCS12_keygen() to be exposed.
### FIXME: this function needs an additional 'usage' parameter
### in OpenSSL:
# define PKCS12_KEY_ID 1
# define PKCS12_IV_ID 2
# define PKCS12_MAC_ID 3
Is it ok to submit a PR for this 'legacy' functionality?
So you want access to the PKCS12 PBE KDF but not PKCS12 enveloping? I'm reluctant to expose that alone since it's really only useful for building a PKCS12 implementation.
For RC2: what's your use case? Exposing extremely legacy ciphers like RC2 needs a compelling reason (e.g. it's used in some major protocol we aren't getting rid of any time soon).
PKCS12 PBE KDF : agreed; this is a baby step, because CMS+ASN.1 (ContentInfo etc) is quite a big undertaking.
RC2: Its use case is for full PKCS12 support with PBE-SHA1-RC2-40 and PBE-SHA1-RC2-128 being in the "official" list of PBE1 algos for PKCS12, and also in OpenSSL.
ASN.1 can currently be handled by pyasn1 or asn1crypto and these 'legacy' cryptos would allow cryptography to be the only supporting library. As an experiment, my script attempts to decrypt all P12 files I can find, using asn1crypto+cryptography. It is these two missing algorithms that require me to resort to other libraries.
For comparion: pyjks and oscrypto both have their own implementations of PKCS12 PBE KDF
ugh, RC2 what a pain. @alex do you have an opinion here? I think I'm okay with adding RC2 (with the standard big pile of warnings in our docs and the caveat that it's not unheard of for OpenSSL to be compiled without RC2 support these days). Not sure about the PKCS12 PBE KDF though. @aalba6675 is that KDF specified in an RFC or just in PKCS12?
Are people actually encrypting things with RC2 in the realworld? -- I
realize it's listed in the spec, but if you're actually using it in this
day and age..
On Tue, Feb 14, 2017 at 6:23 AM, Paul Kehrer notifications@github.com
wrote:
ugh, RC2 what a pain. @alex https://github.com/alex do you have an
opinion here? I think I'm okay with adding RC2 (with the standard big pile
of warnings in our docs and the caveat that it's not unheard of for OpenSSL
to be compiled without RC2 support these days). Not sure about the PKCS12
PBE KDF though. @aalba6675 https://github.com/aalba6675 is that KDF
specified in an RFC or just in PKCS12?—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/pyca/cryptography/issues/2860#issuecomment-279719965,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAADBF_TeinfmE2Ndj124yi8CIBF-5FBks5rcbjYgaJpZM4H53fx
.
--
"I disapprove of what you say, but I will defend to the death your right to
say it." -- Evelyn Beatrice Hall (summarizing Voltaire)
"The people's good is the highest law." -- Cicero
GPG Key fingerprint: D1B3 ADC0 E023 8CA6
The issue is reading p12 archives created using other software. I know Windows defaults to very poor security when using the GUI to export keys as p12/pfx.
Right, I understand that the use case is decrypting p12s that other software creates. What I'm trying to understand is what is this garbage software that is seriously using RC2 in this millenia, and why :-)
The PKCS12 KDF is documented in https://tools.ietf.org/html/rfc7292#appendix-B
Seriously, exposing RC2 is a lesser priority than the KDF.
It just allows us implementers to have the warm fuzzy feeling we support everything in RFC 7292 Appendix C
https://tools.ietf.org/html/rfc7292#appendix-C
Looking at pkcs12.h we do not have to expose the legacy weak algorithms(block/stream ciphers primitives)
to support PKCS#12 files in the wild that are still using non-PBES2 algorithms(Java compatibility comes to mind).
It is sufficient to expose
PKCS12_pbe_crypt (pkcs12.h)
PKCS5_pbe_set (x509.h)
KDF: PKCS12_key_gen_asc (pkcs12.h)
as well as the NIDs
obj_mac.h:#define NID_pbe_WithSHA1And128BitRC4 144
obj_mac.h:#define NID_pbe_WithSHA1And40BitRC4 145
obj_mac.h:#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC 146
obj_mac.h:#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC 147
obj_mac.h:#define NID_pbe_WithSHA1And128BitRC2_CBC 148
obj_mac.h:#define NID_pbe_WithSHA1And40BitRC2_CBC 149
Presumably these wrapper functions call the legacy/weak primitives behind the scenes.
Would this be an acceptable compromise?
If we're looking to first parse both legacy and "modern" PKCS12 then d2i_PKCS12_bio and PKCS12_parse should be able to do it, correct?
To write legacy-compatible PKCS12 encrypted bags we'll need at least some of what you've documented, but we should get reading functioning first.
Is this feature available in current version?
No, no one has contributed support for this yet (and it hasn't reached the top of the priority heap for the core devs).
I think we've overcomplicated this. PKCS12 is a super complex format but what people want is in reality a very, very small subset of it. OpenSSL's PKCS12_parse only supports a single private key + cert + optional cert chain and Go's golang.org/x/crypto/pkcs12 only supports single private key + cert via func Decode(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, err error). Accordingly, I'd like to propose serialization.load_pkcs12(data, password, backend). We can have that return a PKCS12 object that, to start, has only certificate and private_key attributes.
The reason for returning a PKCS12 object instance rather than a tuple of (private_key, cert) is that we can add more features to PKCS12 in the future without breaking the API contract.
Ok, with #4553 we now have basic PKCS#12 support. Additional feature requests can be their own bugs.
Most helpful comment
I think we've overcomplicated this. PKCS12 is a super complex format but what people want is in reality a very, very small subset of it. OpenSSL's
PKCS12_parseonly supports a single private key + cert + optional cert chain and Go'sgolang.org/x/crypto/pkcs12only supports single private key + cert viafunc Decode(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, err error). Accordingly, I'd like to proposeserialization.load_pkcs12(data, password, backend). We can have that return a PKCS12 object that, to start, has onlycertificateandprivate_keyattributes.The reason for returning a PKCS12 object instance rather than a tuple of
(private_key, cert)is that we can add more features to PKCS12 in the future without breaking the API contract.