Discussion Draft V.012
May 31, 1996
Microsoft Corporation
Download Microsoft Word (.DOC) format of this document (zipped, 129K).
Note: This is a discussion draft about PFX, which provides a way for clients to transfer personal data from one environment to another without online server intermediaries. As with both SET and STLP, the goal with PFX is to establish a single technology solution (as agreed upon in an open process via an established standards body) to solve an important security need. Microsoft encourages any developer who is interested in this technology to provide comments in the upcoming W3C forums and meetings.
Overview
Definitions
Security
Prerequisite Standards
Data Model
Protocols
User Interface
Exchange Format
APIs
Acknowledgements
Appendix A
Appendix B
Users of public-key technology have a number of data units that should be characterized as "personal property" because:
- Certificates written against the user's own public keys.
- Certificates written against other entities' public keys.
This information constitutes a user's identity in the public-key infrastructure of the Internet. Our user, Alice, cannot accept having her identity locked into only one machine or one browser make and model. Alice may spend hours at the office getting certificates, keys, and secrets on her office IBM-compatible machine with the "Brand X" browser; but then she needs to take them home--securely--to use on her home Macintosh® with the "Brand Y" browser. She should also be able to take them to a neighbor's house, mall, kiosk, and so on.
Alice's identity belongs to her, not to her machine or her browser. She must be able to access her identity, wherever she may be, to interact with other users and systems on the net. She affirms her identity by signing and decrypting documents with her private keys. She gives evidence of prior authentication of her identity by giving copies of her certificates to requesters. She verifies evidence of others' identities by verifying their certificates. She exercises various minor aspects of her identity by employing assorted personal secrets in various protocols.
We use the term personal information to denote the collection of personal data. The rest of this document describes a machine-independent and browser-independent standard for data formats and APIs to support secure export and import of personal information. A machine-independent data format means that personal information exchange (PFX) data exported from one environment--any type of machine, running any browser--can be imported to any other environment. Standard APIs allow software vendors to write cross-platform applications and browsers easily, expecting the APIs to be available in software libraries on every compliant platform. Browsers should implement the user interface, described herein, that calls the APIs. Other kinds of public-key infrastructure (PKI) applications can also call the APIs.
PFX supports both offline and online transports with well-defined risks and protections in each case. Offline transport is the most secure, because Alice can both algorithmically and physically protect the data. A large number of Web clients use telephone lines and modems, and these are probably at least as painful to the user as taking conscious action to transport data offline. The most secure offline transport is acknowledged to be in hardware tokens such as smart cards. However, it will be years before standards are finalized and cards become ubiquitous. In the meantime, we must do the best we can with software. However, PFX formats will work for either hardware or software transports, so they should be compatible with future hardware security tokens. Online transport allows only algorithmic security, but is most convenient for the user. PFX supports online transport with
- PKCS#1: Format for public keys.
- PKCS#5: Algorithms for password-based encryption.
- PKCS#7: Formats for enveloped, encrypted, and signed messages.
- PKCS#8: Format for shrouded private keys.
If an attacker, Mike, intercepts Alice's personal property in transit, Alice will not have the use of it. Worse yet, Mike may impersonate Alice. At the very least, he will gain knowledge of Alice's browsing patterns, her transaction partners and activities, her account numbers, and other secrets. If Mike quietly copies the data, Alice will not know it has been compromised. This is the worst case, because Mike can abuse Alice's identity at the same time Alice uses it. By the time consequences of Mike's actions come back to Alice, she may have suffered irreparable damage to her credit and reputation.
Loss or leakage of private keys is catastrophic, because the potential damage may never be undone. Alice must give keys the utmost protection. Loss or leakage of other confidential data may be discomfiting, so Alice should guard them accordingly. The following table summarizes these risks:
How can Alice protect herself? If she can use long-key, public-key encryption, then she has the best protection currently available against hackers opening her safe. She will have reasonable safety for either online or offline transport.
However, she can only use public-key encryption if she has the PFX key-exchange key of the target machine. This may be inconvenient or impossible. It will be inconvenient if she does not happen to have the target key when the need to transport arises. It will be impossible if she does not know the target machine when the need to transport arises; in other words, if she wants the ability to transport to any machine.
Alice can use password-based encryption in these cases. This encryption method converts a password to the same symmetric cipher key at both ends of the transport. In practice, attackers can guess passwords relatively easily. Alice should protect her encrypted safe physically in password mode. In other words, she should avoid online transport, where surreptitious copying is too easy. If she must use it, she is risking exposure and the possible damages listed in the Risks from Exposure table.
We deem the risk of exposure of password-protected private keys to be too great in the online case. Although we cannot prevent Alice from exporting a password-protected PFX safe containing private keys and foolishly transporting it online, we can take the following measures to protect Alice:
In these cases, we deem it acceptable to transport all but private keys under password protection. We assume that Mike will only find it economical to steal keys. If he steals certificates and CRLs, he might be able to sell traffic analysis to marketing organizations. However, such information is of low value unless very large numbers of victims are exploited, requiring Mike to mount a very large number of guessing attacks. Even in the worst case, the only risk to Alice is exposure. With the assorted secrets, it seems the worst Mike can do is trigger protocol failures in Alice's transactions. In other words, Mike can harass Alice and her transaction partners. However, the Internet exposes Alice to so many other denial-of-service attacks at all levels that the incremental risk due to PFX seems negligible. See Appendix B for more details of the economic argument.
If Alice cannot transport her keys in password mode, how can she access them on multiple machines? A straightforward, but unacceptable, solution is for Alice to download her private keys from a server. This is unacceptable because such a server knows Alice's private keys.
Suppose the server only knew some secrets that Alice, and Alice alone, could use to (re)generate her keys. An attacker who learned these secrets would be able to mount dictionary attacks on Alice's user name and password, but could not learn her keys directly. The risk is considerably lower than the server's knowing her keys. This server is a blind oracle: It tells Alice things only it can tell her, but learns nothing about her secrets in the process. The server's purpose is not only to inject unknowns into the process, but to slow down dictionary attacks.
A constraint is that Alice must initially generate any transportable keys with the same process. If Alice will ever use the PFX private-key generation service for a particular key, she must always use it.
She may also have other keys generated locally and securely in the ordinary way, but these can only be transported in PFX public-key mode.
A corollary is that the oracle cannot depend on authenticating Alice to establish a private channel, because Alice may be using the channel to generate keys, before she has any evidence of authentication, such as certificates against the new keys. We can design a simple protocol that never requires client authentication. The following is a sketch:
- Someone who knows the oracle's secrets can bypass this policy and permit dictionary attacks.
- This delay is the main protection in the scheme, because the oracle does not actually inject entropy by mixing in its secrets: the same service is available to attackers.
- The entropy against dictionary attack is U, that of the user name; plus P, that of the password; and N, that of the key nickname. The entropy against birthday dictionary attacks--finding any valid user name--is roughly U/2 + P + N.
The following table summarizes the protections offered by PFX now and along a foreseeable upgrade arc:
PFX uses abstract syntax notation one (ASN.1) for modeling platform independence and private-key cryptographic standards (PKCS) for modeling security. The designers of PFX consider these choices the only practical ones at the time of writing. We would have preferred simpler data modeling techniques such as Secured Transaction Technology's (STT) binary encoding via Cambridge Prefix Notation or Simple Distributed Security Infrastructure's (SDSI's) similar ASCII S-expressions. But neither is sufficiently widely accepted nor implemented to justify choosing it. PKCS has the further disadvantage of being a privately controlled standard. We would have preferred an open or public standard, but there is none presently available, to our knowledge, with the completeness of PKCS.
ASN.1 and PKCS are practical choices because they are widely, if reluctantly, accepted and widely, if imperfectly, implemented at the time of writing.
The following sections describe syntax and semantics of PFX data.
The entity-relationship diagram (Figure 1) illustrates the PFX data model. In prose:
Each environment has one PFX key-exchange key and one PFX safe. The safe has four compartments:
2.1. Personal Certificates that are written against Alice's public keys.
2.2. Others' Certificates that affirm the identities of other entities.
2.3. CRLs from all sources; kept together.
Figure 1. Entity-relationship diagram
The safe itself is labeled with its protection mode, either PUBLIC_KEY_MODE or PASSWORD_MODE. It is also labeled with its transport mode, either OFFLINE or ONLINE. The safe must not contain private keys if its protection is PASSWORD_MODE and its transport is ONLINE.
The encryption method is further identified with a PKCS Algorithm Identifier, in the clear. This allows target software to decrypt.
Each key has a locally unique nickname in a human-readable string. This nickname is assigned by Alice and must be the same in all her environments. Each key is marked either regenerable or non-regenerable. Each key also points, via thumbprint, to one or more personal certificates that have been written against its corresponding public key. (Thumbprints are defined in the next paragraph.) An exported safe must not contain keys if the transport mode is ONLINE.
Each certificate or CRL has a category, which is either certificate or CRL. It also has a type, which is X.509, SDSI, or other. Interoperability is not defined for certificates and CRLs of type other. If a type is SDSI, the category must not be CRL. Each has a statistically globally unique thumbprint, which is simply its SHA-1 hash. Each X.509 certificate or CRL also has a globally unique name consisting of an Issuer and a Serial Number.
Each secret has a locally unique name in a human-readable string. This name is assigned by Alice and must be the same in all her environments.
The extension technique is modeled after X.509. Each extension has a globally unique object identifier (OID) of ASN.1 type OBJECT IDENTIFIER, allowing software to dispatch to processing routines if it knows the OID. Each also has a criticality flag; if software does not know the OID and the criticality flag is TRUE, software must abort. Each extension also has a binary value, whose semantics depend on the OID.
Figure 2. Public-key mode
In this mode, Alice takes a diskette containing her home machine's PFX public key-exchange key (PPKEK) to the office in the morning. This key--and its corresponding private key--was generated when Alice installed the PFX system on her home machine. After logging Alice on, the office machine's PFX system allows Alice to encrypt her PFX safe with the PPKEK, creating a PK-Enveloped PDU. Alice can e-mail the PDU home, put it on a server, or take it home on a diskette. This is standard public-key enveloping of Alice's safe, as used in many accepted secure protocols.
More formally, to transport the safe from environment A to environment B, Alice must:
3.1. Encodes, that is, streams the PFX safe data into a buffer, X, in a machine-independent format.
3.2. Generates a fresh, random, bulk-data, symmetric encryption key, K.
3.3. Encrypts X with key K, resulting in EPFX.
3.4. Encrypts key K with the PPKEK of environment B, resulting in EK.
3.5. Packages EPFX and EK into a PFX safe PDU.
5.1. Unpacks the safe PDU, yielding EPFX and EK.
5.2. Decrypts EK, yielding K.
5.3. Decrypts EPFX with K, yielding a buffer containing the encoded PFX safe data.
5.4. Decodes the data, that is, transforms it into a convenient, internal representation.
5.5. Installs the data, following some per-object, common-sense overwrite-confirmation rules explained in section 8, Exchange Format.
Figure 3. Password mode
In this mode, Alice does not need her home machine's PPKEK. She creates and remembers a session password. The office machine's PFX system derives an ordinary, symmetric encryption key from Alice's user name and password and encrypts the PFX plaintext with this key.
We considered the option of folding in entropy from private-key nicknames from the name strings of personal secrets to increase security. This will work if Alice accepts the burden of remembering all these strings and typing them in on the target machine or if the target machine is pre-loaded with these names. We consider both possibilities to be sufficiently remote to reject the idea at present.
Alice's implementation will only save password-encrypted PFX bits to files, and admonishes her not to send the bits home online in this mode, because the system cannot assure the strength of her password. When Alice gets home, she types in the same user name and password, with which the home PFX system decrypts the bits.
More formally, Alice must:
1.1. Solicits a new PFX password and, optionally, a PFX user name from Alice. The user name may be taken from the system.
1.2. Solicits a choice of transport mode from Alice.
1.3. Generates a fresh, random bit string for key-generation salt.
1.4. Runs the PFX password, the user name, the list of selected private-key nicknames, the name strings of all personal secrets, and the salt through the SHA-1 hash function, producing a new symmetric encryption key, K.
1.5. Encodes the PFX safe data into a buffer X, omitting private keys if the transport mode is ONLINE_MODE.
1.6. Encrypts X with key K, resulting in EPFX.
1.7. Packages the salt and EPFX into a PFX safe PDU.
3.1. Unpacks the safe PDU, yielding EPFX and salt.
3.2. Solicits the PFX password and user name from Alice.
3.3. Runs the PFX password, the user name, and the salt through a hash function, regenerating K.
3.4. Decrypts EPFX with K, yielding the encoded PFX safe data.
3.5. Decodes the data.
3.6. Installs the data, following per-object, common-sense overwrite-confirmation rules explained in section 8, Exchange Format.
Alice may select this option on any machine. It will result in the same key material given the same user name, password, and key nickname. The PFX installation has the key-exchange certificate of the key-generation oracle. This option is separate from the export and import options.
Figure 4. Private-key generation
More formally:
1.1. Let H(x) denote a collision-free, one-way hash of the bit string x, namely SHA-1. It is infeasible to find an x and a y such that H(x) = H(y) or to learn x from H(x).
- Let h be the constant bit length of H(x). For SHA-1, it is 160 (128-bit MD5 is not recommended)
1.2. Let either x|y or {x, y} denote the concatenation of bit string x and bit string y.
1.3. Alice's secrets (an attacker stealing these will be able catastrophically to impersonate Alice):
- u is a bit-string containing Alice's PFX user name. This must be the same in all of Alice's environments.
- p is a bit-string containing Alice's key (re)generation password. This must be the same in all of Alice's environments. It may (and should be) different from any of Alice's other passwords.
- n is a nickname Alice applies to a given private key. This allows Alice to regenerate multiple, named sets of private keys in any environment.
1.4. Let v be the bit length for the private key with nickname n. For signature private keys, a typical length is 1024.
1.5. The oracle's secrets (an attacker stealing these may be able to act as another oracle and bypass procedural protections against dictionary attacks on Alice's password):
- Let S be a sequence of permanent, but random numbers, s1, s2, ..., sk, where k = ceil(v/h). There are enough numbers in the sequence to produce hashes that, when concatenated, meet or exceed the bit length, v, of the desired private key. The oracle has enough of these on hand to meet a request for a private key of any reasonable length.
1.6. Assume a secure channel with an authenticated server between the oracle and Alice.
2.1. Alice sends req = {v, H(u), H(u|p|n)} to the oracle.
2.2. The oracle saves H(u) for a reasonable time and checks repeated requests against it to stop attackers mounting high-frequency dictionary attacks. A reasonable policy might be to allow five requests per hour on the same H(u). The oracle does not know u, p, or n, so cannot tell whether a request was successful. Only time-based policies seem useful. Someone impersonating the oracle can bypass this policy and permit dictionary attacks.
2.3. The oracle sends resp = {H(z1), H(z2), ..., H(zk)}, where zi = {H(u|p|n), si}. In other words, the oracle rehashes the hash of Alice's secrets, H(u|p|n), with each of its own secrets. It computes enough of these rehashes to give Alice plenty of bits to generate a long private key.
2.4. Alice generates her key by a deterministic process from the low-order v bits of {H(w1), H(w2), ..., H(wk)}, where wi = {u, p, n, zi}. In other words, Alice rehashes the oracle's responses with her original secrets, u, p, and n to ensure that an eavesdropper intercepting the responses cannot regenerate her key, because the eavesdropper does not know the secrets. The deterministic process might be, for example, searching for the next higher prime number.
The following scenario is just an example. This document does not aim to specify user interface in detail.
To take her safe home from the office, Alice performs the following procedure with her "Brand X" browser:
2.1. Select from the radio button group:
- Password Mode radio button. If Alice selects this and clicks OK in this dialog, she gets the second-level dialog box that states the following: "Please enter a new password to secure the export of your personal information." This dialog box also displays the usual admonitions that the password must be long, difficult to guess, easy to remember, and not written down; but if so, kept separate from the protected data. For example, "Warning! If you forget the password you will not be able to import personal data," and so on.
- Public-Key Mode radio button. If Alice selects this and clicks OK, she is prompted for a file to open. If Alice brought a floppy with the key in a file called homekey.pfx, she would insert the disk, navigate over to it, and select that file. The system would verify a certificate-like syntax with self-signature on the key and import it to the cryptosystem, in anticipation of using it to envelope.
- In fact, Alice selects the Public-Key Mode radio button and inserts the right diskette.
2.2. Review the Private Keys check box. It is grayed if Alice selected Password Mode. If it is not grayed, Alice checks this box.
- If Alice has more than one private key set, a drop-down list of existing key set nicknames, with all selected, is enabled. Alice can drop this down and press SHIFT or CTRL and click to select or cancel the selection of various nicknames.
2.3. Review the Certificates & CRLs check box. Alice checks this box.
2.4. Review the Personal Secrets check box. Alice checks this box.
- Another drop-down list of secret names, with all selected, is enabled. Alice may press SHIFT or CTRL and click to select or cancel the selection of various secret names.
- Another application is needed allowing Alice to name secrets and install them in the safe.
2.5. Select the E-mail or File Transport radio button. The e-mail radio button would be disabled if Alice had selected the Password Mode radion button. Alice chose Public-Key Mode, so she selects the E-mail radio button.
2.6. Enter e-mail address or filename into text box. Alice enters her own e-mail address, "Alice@bletch.com". She will dial into her mail server from home and pick up the personal information there.
2.7. Click OK.
When she gets home, she opens her e-mail and sees a MIME attachment icon containing her personal information. The "Brand Y" browser supports PFX Importation by MIME type, so all she needs to do is double-click on the MIME attachment in the e-mail message. If she had chosen password mode, she would be prompted for the password.
Alice can now use all the data she had at the office at home. Also, if she had any preexisting data at home, it is preserved unless she specifically chose to overwrite it. She can do everything she could do at the office, plus everything she could previously do at home.
ASN.1 and Distinguished Encoding Rules (DER) encoding ensure environment-independence.
Commentary is in-line.
This section is a refinement of the data model in section 5.
First, establish an ASN.1 module named "PFX" and note that its default ASN.1 tags are explicit.
PFX DEFINITIONS EXPLICIT TAGS ::= BEGIN
Next, import, in the ASN.1 sense, definitions from several standards and export all data types defined in this module.
IMPORTS ContentInfo FROM PKCS7 pkcs7 EncryptedPrivateKeyInfo FROM PKCS8 pkcs8 Name, CertificateSerialNumber FROM X509 x509; -- EXPORTS All;
The top-level definition is the PersonalInformationExchange. This is the type for personal information in a PKCS#7 ContentInfo whose contentType is either envelopedData or encryptedData.
PersonalInformationExchange ::= ContentInfo
The plaintext is of type SafeContents. It contains a globally unique identifier, pfxOID, registered with an appropriate authority. It will collide with no other OID. Version is an integer that serves to break backwards compatibility: software shall be written to abort if it does not explicitly handle the version in any given instance of this type. Its present value is 1. The remaining four items in the sequence are the meat. CertAndCRLBag, KeyBag, and SecretBag are self-explanatory. Extensions is a well-known technique borrowed from the X.509 certificate standard to support forward and backward compatibility. The IMPLICIT keywords denote optimizations that save a few bytes of tag data.
SafeContents ::= SEQUENCE { pfxOID OBJECT IDENTIFIER -- Value TBD version Version (v1(1)), certAndCRLBag [0] IMPLICIT CertAndCRLBag OPTIONAL, keyBag [1] IMPLICIT KeyBag OPTIONAL, secretBag [2] IMPLICIT SecretBag OPTIONAL, extensions [3] Extensions OPTIONAL } Version ::= INTEGER
A CertCRLBag contains certificates and CRLs. When this specification is finalized, it should be written to contain options for all known standardized certificate formats. For now, it contains an X.509 bag, an LDAP bag, and an SDSI bag; the latter two being just examples.(Please note that several of the links below point to servers that are not under Microsoft's control. Please read Microsoft's official statement regarding other servers.) Information on LDAP can be found at http://ds.internic.net/rfc/rfc1777.txt. LDAP does not currently define certificates, but most likely will do in its next version. For more information on SDSI, go to http://theory.lcs.mit.edu/~rivest/sdsi.ps
and http://theory.lcs.mit.edu/~rivest/
.
CertCRLBag ::= SEQUENCE { x509Bag [0] IMPLICIT X509Bag OPTIONAL, ldapBag [1] IMPLICIT LDAPBag OPTIONAL -- this is just a sample sdsiBag [2] IMPLICIT SDSIBag OPTIONAL -- another sample -- etc. }
Each X.509 certificate and CRL is conveniently captured, with some small overhead, in an instance of a PKCS#7 ContentInfo, containing an empty SignedData and a NULL signature. This is explicitly allowed in the standard and is a common idiom. A thumbprint is included in the bag for correlation of the certificate with private keys. The type of the thumbprint is DetachedDigest, another PKCS idiom.
X509Bag ::= SEQUENCE { certOrCRL ContentInfo, thumbprint Thumbprint }
The following allows the current sample syntax to be complete, though underspecified.
LDAPBag ::= SEQUENCE { value TBD, thumbprint Thumbprint } SDSIBag ::= SEQUENCE { value TBD, thumbprint Thumbprint } Thumbprint ::= DetachedDigest TBD ::= ANY
A KeyBag is a sequence of PKCS#8 PrivateKeyInfos, each associated with
KeyBag ::= SEQUENCE OF PrivateKey PrivateKey ::= SEQUENCE { assocCerts SEQUENCE OF Thumbprints, regenerable BOOLEAN DEFAULT FALSE, nickname UniversalString, pkcs8data PrivateKeyInfo }
Issue: is UniversalString the right ASN.1 type for a key nickname, or is BMPString better?
Alice's personal secrets are contained in an instance of SecretBag, which, in turn, contains multiple values named with strings Alice assigns. The user interface shall solicit confirmation if Alice attempts to overwrite an existing compartment with another one that has the same name. Compartment names are local to Alice's environments and under the control of her and her application software.
SecretBag ::= SEQUENCE OF Secret Secret ::= SEQUENCE { secretName UniversalString, value OCTET STRING -- defined by compartment name }
PFX must allow extensibility. For example, protocol secrets from well known, published protocols like SET (http://www.visa.com) can be labeled with OIDs and should be part of the safe. Older software must not break when it reads messages containing new objects. It must, at least, ignore data it cannot interpret. The mechanism for intentionally breaking this compatibility is the top-level Version field in the PersonalInformationExchange. Older software is required to report error when reading a PersonalInformationExchange with a version it does not know.
PFX borrows its extensibility mechanism from X.509. An Extension is a sequence of a globally unique extension identifier, assigned by a central authority; a flag indicating criticality, and a value. Software shall parse any extensions present in a PersonalInformationExchange and behave as follows:
-- Modeled after X.509 -- -- If the extnId is known -- process the extnValue according to published specifications -- else -- if "critical" is true -- error -- else -- ignore the extension Extensions ::= SEQUENCE OF Extension Extension ::= SEQUENCE { extnId OBJECT IDENTIFIER, critical BOOLEAN DEFAULT FALSE, extnValue OCTET STRING }
Finally , PFX needs encryption algorithm identifiers. The following are taken from PKCS#1, #5, and SET:
secsig OBJECT IDENTIFIER ::= {iso(1) identified-organization(3) oiw(14) secsig(3)} id-sha1 OBJECT IDENTIFIER ::= {secsig 2 26} -- -- RSA encryption of OAEP'd KEK and SHA1 hash of the "Content", where -- the "Content" is defined as with the signature digital operation. -- rsa1 OBJECT IDENTIFIER ::= {iso(1) member-body(2) us(840) rsadsi(113549)} pkcs-1 OBJECT IDENTIFIER ::= {rsa1 pkcs(1) 1} pkcs-5 OBJECT IDENTIFIER ::= {rsa1 pkcs(1) 5} pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} -- insecure; do not use pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} -- proposed to RSA pbeWithSHA1AndRC4 OBJECT IDENTIFIER ::= {pkcs-5 12} -- proposed to RSA rsaEncryption OBJECT IDENTIFIER ::= {pkcs-1 1} rsaOAEPEncryption OBJECT IDENTIFIER ::= {pkcs-1 6} rsaOAEPEncryptionOfKeySHA1 OBJECT IDENTIFIER ::= {rsaOAEPEncryption 1} -- missing: contentEncryptionValues for DES-CBC, RC2-CBC, RC4, and CDMF
Note that MD5 has been cryptanalyzed and is no longer secure (private communication). RSA will provide updated algorithm identifiers; we have proposed pbeWithSHA1AndRC2 and pbeWithSHA1AndRC4.
This is the end of the entire PFX module.
END
These APIs cover only import and export. PFX key generation is a separate process not requiring APIs.
typedef long int PFXERR; // PFX error code #define PFXERR_NO_ERROR 0x00000000 #define PFXERR_WARNING_BUFFER_POINTER_NULL 0x00010001 #define PFXERR_ERROR_INSUFFICIENT_SPACE 0x00020001 #define PFXERR_ERROR_UNKNOWN_MODE 0x00020002 #define PFXERR_ERROR_INVALID_TRANSPORT 0x00020003 #define PFXERR_ERROR_INVALID_PKEK 0x00020004 #define PFXERR_ERROR_PRIVATE_KEY_NOT_FOUND 0x00020005 #define PFXERR_ERROR_UNKNOWN_ALGID 0x00020006 #define PFXERR_ERROR_INVALID_STRING_ARRAYS 0x00020007 #define PFXERR_ERROR_INVALID_HANDLE 0x00020008 #define PFXERR_ERROR_INVALID_INOUT_PARAMETER 0x00020009 #define PFXERR_ERROR_INTERNAL_ERROR 0x0002ffff typedef unsigned char BYTE; // should work on 8-bit byte machines typedef unsigned short int WORD; // should work on 32-bit machines typedef unsigned long int DWORD; // ditto typedef void* HANDLE; // identifies temporary saved state typedef struct s_PFX // Instances contain DER-encoded PFX { // (see the ASN.1 definitions, above) BYTE *pbPFX; // Pointer to data buffer DWORD cbPFX; // number of bytes needed } PFX; typedef struct s_PKEK // PFX environment's Public Key-Exchange Key { BYTE *pbPKEK; // Pointer to data buffer DWORD cbPKEK; // number of bytes needed } PKEK; typedef struct s_ALGID // PKCS#7 or #5 Algorithm Identifier { BYTE *pbAlgid; // Pointer to data buffer DWORD cbAlgid; // number of bytes needed } ALGID; #define PFX_PASSWORD_MODE 1 #define PFX_PUBLIC_KEY_MODE 2 #define PFX_ONLINE_TRANSPORT 4 #define PFX_OFFLINE_TRANSPORT 8 typedef struct s_CHARSTRING { BYTE fUnicode; // non-zero if strings are double-byte BYTE fOverwrite; // non-zero if Overwriting is desired. BYTE *pbCharString; // Pointer to data buffer DWORD cbCharString; // number of bytes needed } CHARSTRING; typedef struct s_STRARRAY { DWORD cStrings; // number of strings in the array CHARSTRING *rgStrings; // pointer to first string } STRARRAY;
Implementations bear the responsibility for DER-encoding and decoding the PFX binary.
The following API initializes the entire PFX import and export system, freeing any internal state memory.
void PFXInit(void);
To export an entire PersonalInformationExchange data unit from an environment-dependent store into a memory buffer, call this API:
HANDLE PFXExport ( DWORD dwProtectionModeInput, DWORD dwTransportModeInput, PKEK *pPKEKInput, ALGID *pKeyEncryptionAlgidInput, ALGID *pContentEncryptionAlgidInput, );
If any PFX import / export API ever returns a NULL handle, call
PFXERR PFXGetLastError(void);
to find the error.
In PFXExport, dwProtectionModeInput must be either PFX_PASSWORD_MODE or PFX_PUBLIC_KEY_MODE. If it is neither, then PFXExport returns a NULL handle and PFXGetLastError returns PFXERR_ERROR_UNKNOWN_MODE.
dwTransportModeInput must be either PFX_ONLINE_TRANSPORT or PFX_OFFLINE_TRANSPORT. If it is neither, then PFXExport returns a NULL handle, and PFXGetLastError returns PFXERR_ERROR_INVALID_TRANSPORT. If it is PFX_ONLINE_TRANSPORT, PFXGetPDU (documented in the code below) will leave the key bag empty.
If dwModeInput is PFX_PUBLIC_KEY_MODE, then pPKEKInput must point to a PKCS#7 ContentInfo with contentType SignedData whose SignerInfos contains a self-signed X.509 certificate that contains the public key-exchange key of the receiving machine. Syntax errors or failure of the signature check results in a NULL handle and PFXGetLastError's returning PFXERR_ERROR_INVALID_PKEK.
If both mode and certificate checks are valid, then the function next examines pAlgidInput. If in password mode, this must point to a DER-encoded OBJECT IDENTIFER value equal to pbeWithSHA1AndRC2-CBC or pbeWithSHA1AndRC4. If in public-key mode, pKeyEncryptionAlgidInput must point to the value rsaOAEPEncryption or rsaOAEPEncryptionOfKeySHA1 and pContentEncryptionAlgidInput must point to the value DES-CBC, CDMF, RC2-CBC, or RC4 (issue: we must get real values for these).
If PFXExport returns a non-NULL handle, pass it to the following API to retrieve the encrypted PFX safe PDU:
PFXERR PFXGetPDU(HANDLE hPFX, PFX* pPFXPDUOutput);
This API validates the buffer pPFXPDUOutput, and possibly fills it with content, according to the following caller-allocates logic:
Caller-allocates Buffer Management
Overwrites cbProvided with cbNeeded (that is, set pPFXPDUOutput->cbPFX = cbNeeded;)
return PFXERR_WARNING_BUFFER_POINTER_NULL
}
Else {
If cbProvided is greater than or equal to cbNeeded {overwrite the buffer with the data
overwrite cbProvided with the number of bytes actually copied
return PFXERR_NO_ERROR
}
Else {
overwrite the buffer with cbProvided bytes of data, truncating the data transferoverwrite cbProvided with cbNeeded
return PFXERR_ERROR_INSUFFICIENT_SPACE
}
}
The application may either call PFXGetPDU twice--once to find out the needed size and to allocate a buffer, and the second time to get data--or once, providing a buffer large enough to handle the data in any event. Applications must free allocated space in pPFXPDUOutput after the data has been used.
End of Buffer Management
The contents of pPFXPDUOutput may be written to a disk file or a MIME object for transport. MIME transport should be discouraged in password mode.
When complete, the application should free its own memory and call
void PFXFreeHandle (HANDLE hPFX);
To import a package of certs and CRLs from a memory buffer into an environment-dependent store, call the following:
HANDLE PFXImport ( DWORD *pdwConfirmOverwrites, PKEK *pPKEKInput, PFX *pPFXPDUInput );
The application must provide the self-signed certificate pPKEKInput for import; the function uses this certificate to look up the corresponding private key for decryption. If the certificate is invalid, PFXImport returns a NULL handle and PFXGetLastError returns PFXERR_ERROR_INVALID_PKEK. If the private key cannot be found, PFXImport returns a NULL handle and PFXGetLastError returns PFXERR_ERROR_PRIVATE_KEY_NOT_FOUND.
If pdwConfirmOverwrites is an invalid pointer, then PFXImport returns a NULL handle and PFXGetLastError returns PFXERR_ERROR_INVALID_INOUT_PARAMETER.
If PFXImport returns a valid handle and loads pdwConfirmOverwrites with a non-zero (TRUE) value, call the following API to get arrays of strings to present to the user for confirmation:
PFXERR PFXImportGetConfirmationStrings ( HANDLE hPFX, STRARRAY *pStrArrayKeysToOverwriteInputOutput, STRARRAY *pStrArraySecretsToOverwriteInputOutput );
This API allocates space for the strings because the handshake between caller and callee would be too complex in a caller-allocates case. If it cannot allocate storage, it will return PFXERR_ERROR_INTERNAL_ERROR.
The CHARSTRINGs in the STRARRAYs will all have FALSE=0 for values of their fOverwrite fields. The application should solicit confirmation from the user for each string in an appropriate user interface, flip the corresponding fOverwrite flag fields for those fields that should be overwritten, and call the following API:
PFXERR PFXImportSetConfirmationStrings ( HANDLE hPFX, STRARRAY *pStrArrayKeysToOverwriteInput, STRARRAY *pStrArraySecretsToOverwriteInput );
which will deallocate the STRARRAYs and return PFXERR_NO_ERROR in the normal case and PFXERR_ERROR_INTERNAL_ERROR otherwise.
If the application does not call PFXImportSetConfirmationStrings, no overwriting will take place. In any case, the application must call
PFXERR PFXCompleteImportation ( HANDLE hPFX, DWORD *pdwModeOutput, ALGID *pKeyEncryptionAlgidOutput, ALGID *pContentEncryptionAlgidOutput, )
Because the PFXInput contains a self-describing encrypted data object, the function reports the PFX protection mode and encryption algorithms used in the output parameters dwModeOutput, pKeyEncryptionAlgidOutput, and pContentEncryptionAlgidOutput. If any of these pointers are NULL, the function ignores them. If they are non-null, the function employs a caller-allocation buffer management discipline like that in section 9.2, Export for the algorithm identifiers. The caller may reallocate and retry, at low overhead, as may times as necessary.
When done, the application calls PFXFreeHandle, as with PFXExport.
Applications will need finer control over an environment's certificate store, specifically to add, delete, search on a variety of keys, and to verify. Environment vendors shall supply their own solutions to these problems.
PFX was designed by Brian Beckman, Terence Spies, and Josh Benaloh. Yacov Yacobi made substantial analytical comments. All are affiliated with Microsoft Corporation.
PKCS#8 and #5 explicitly provide encrypted data exchange formats for single private keys. The PFX proposal in password mode extends the symmetric key, password-based methods of PKCS#5 to cover transport of the entire safe, including private keys. Its specific algorithms are a bit dated, but we expect stronger algorithms to be registered with RSADSI in the near future. We are proposing pbeWithSHA1AndRC4 and pbeWithSHA1AndRC2-CBC for inclusion in the next revision.
PKCS#5 encryption is symmetric. The password implies the key. The user provides the password at encryption time and again at decryption time. PKCS#5 and the present standard have no provisions for managing the secret key or the password: that is the user's responsibility. Vendors shall supply prudent user interface or wizards to help users avoid mistakes.
Here, we analyze the decision process of an attacker, Mike, who wishes to open a copy of Alice's safe to abuse her secrets. We assume that Mike cannot break a safe protected by public-key encryption; only password-protected safes are even thinkable. Mike will incur a certain expected cost, $C, to break Alice's safe. If Mike's potential gain from abusing Alice's identity is greater than $C, then Mike will do it.
First, we do a concrete analysis with placeholder numbers. We then move to an abstract formula. Assume that, between her user name and password, Alice provides 40 bits of entropy for key generation. This is equivalent to eight characters chosen randomly from a 32-character alphabet. This assumption may be rather generous, becausee Alice will not choose randomly, but from a relatively small dictionary of natural language words with, perhaps, an occasional noise character or gratuitous case change.
The analysis scales linearly with any assumed amount of entropy. In practice, 40 bits is probably the best case; the average case is probably much less, perhaps as little as 30 bits. Continuing with the numbers for 40 bits, Mike will have to do no more than 2^39 trial decryptions, on the average, to open Alice's safe. 2^39 is about 500 billion. At a rate of 1000 decryptions per second, Mike will need 500 million machine-seconds, or about 2 weeks on 500 machines. If a capable machine costs $2,000, then Mike must spend 1 million to start. If he must recover his investment in two years, then he has to make 1 million in 100 weeks, or about $10,000K per week. That translates into $20,000 per breakage.
Because Mike is a crook, he has probably spent much less than $2,000 per machine, so $20,000 is an upper limit to C. Furthermore, because Alice's protection is probably much less than 40 bits, Mike probably breaks her safe much faster, further reducing C. But, even if Mike spends too much, if he can steal private keys, he might be able to forge $20,000 worth of transactions before moving on. It is hard to see how he could recoup $20,000 by stealing only certificates, CRLs and assorted secrets. If his costs were $200--to orders of magnitude less--he might be able to recoup that little.
Algebraically, this little linear analysis is the following:
Note that, given a constant amortization time, the cost per safe is independent of the number of machines.