PKCS#1 vs PKCS#8 vs PKCS#12 for RSA keys - cryptography

What is the recommended RSA key format to use if you only started using it nowadays?
I know that PKCS#1 is a format dedicated to RSA keys but do I need to avoid using it because it's old?
recommended RSA key format to use will be
PKCS#1, PKCS#8 or PKCS#12 ?

TL;DR: Use PKCS#1 only within your own identified scheme, use "inner" PKCS#8 / SPKI if you want to identify a key in a scheme. Use encrypted PKCS#8 when storing private keys and no better method is available; use PKCS#12 if you want to accomplish the same thing and you are using PKIX / X.509. PKCS#12 can also be used as a trust store, usually using a separate file.
I'll cover this because it is more about choosing an encoding than the inner working of RSA and other algorithms. If that wasn't the case then it should be posted on Cryptography, after searching for an answer on that Q/A site, of course.
First, here are the standards that we are talked about. They have been initially been created by RSA Laboratories, but currently they are being maintained as RFC's:
PKCS #1: RSA Cryptography Specifications Version 2.2: these specify the RSA cryptosystem, as well as specifying how the public- and private keys can be encoded.
PKCS #8: Public-Key Cryptography Standards (PKCS) #8:
Private-Key Information Syntax Specification Version 1.2 : This documen specifies "inner" PKCS#8 which describes the private key type and contains the encoded private key and the "outer" PKCS#8 which creates a cryptographic wrapper that can be used to encrypt the private key using a symmetric algorithm such as 3DES or AES.
PKCS#12: PKCS #12: Personal Information Exchange Syntax v1.1 : Despite the broad wording of the title, this is "a transfer syntax for personal identity information, including private keys, certificates, miscellaneous secrets, and extensions", i.e. it is about "personal information" in the form of cryptographic objects.
Another important document (or really set) was initially created by ITU-T, formerly known as CCITT, an international treaty organization:
X.509 is the basic standard for (digital) certificates, which are a mechanism to infer trust for public keys and related (identity) information contained within certificates, and to allow revocation of those certificates.
There are number of other standards in the X.5nn and X.6nn series that support X.509, but people generally just say "X.509" to mean all of them together.
However, the X.509 standards are quite large and complex, and back when they were new cost money to obtain, so IETF (the Internet Engineering Task Force) created a series of RFCs that form a "profile" (effectively, a subset) of X.509 for Internet use, called PKIX (Public Key Infrastructure using X.509). The main one here is:
RFC5280 Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile: this is the main standard that describes certificates and revocation lists, which are used by e.g. TLS for server and sometimes client authentication, by CMS and S/MIME for signing and/or encrypting data and email, for RFC3161 timestamping, in "JOSE" (JSON-based cryptography), and more.
just as X.509 is supported by other X-series standards, RFC5280 is supported by a number of other, related RFCs. In particular the representation of public keys IN PKIX certs is defined in RFCs 3279, 4055, 4491, 5480, 5756, 8410, 8692, 9295 (at least, there may be more I've missed).
First note that these standards are not independent of each other. PKCS#12 depends on PKCS#8 to encode the private key and X.509/PKIX to encode the certificates within this "container format". PKCS#8 depends on PKCS#1 to encode the private key when it is an RSA key (pair), and X.509/PKIX similarly uses PKCS#1 for the public key. PKCS#8 originally used PKCS#5 (not listed above) for password-based encryption, but PKCS#12 defined additional password-based encryption schemes, and now both PKCS#8 within PKCS#12 and "standalone" PKCS#8 frequently use either the PBEs from PKCS#12 or the "PBES2" scheme from PKCS#5v2 (that v2 is critical; the PKCS#5v1 schemes are now broken and obsolete).
These structures can and often are stored in text rather than binary, in which case the specifications of PEM in RFC 1421 and the extensions for PKIX related structures in RFC 7468 should be consulted.
Which one to use?
Now comes the question which one to use. However, before we talk about storing private keys: private keys have been designed to remain private. That means that you should choose the most secure method of storing and using them (that still would help fulfill your use case). Quite often it is better to generate and store private keys within a secure container such as a hardware device (HSM, TPM) or a system provided certificate- or key store.
After that it depends on what you are trying to achieve.
PKCS#1
PKCS#1 describes a simple, near-minimal format for an RSA public or private key. So if you're handling raw private keys and need to store them on a medium, you need some way to encode the key. This is why the leading RSA specification contains a method of encoding them. So you'd use this standard when you'd work with RSA on a relatively low level, basically when you'd have to specify your own protocol (which you should do if you'd use RSA at such a low level, cryptographic protocols should deserve their own specific section in the documentation).
Notes:
The PKCS#1 format for the private key also contains the public exponent. That means that it is easy to extract the public key from the private key.
PKCS#1 is often also stored in textual format called PEM, where it has "RSA PUBLIC KEY" or "RSA PRIVATE KEY" in the header. As you can see, the PEM header contains the key type to be able to distinguish between key types and their respective encoding formats.
PKCS#8
The inner format within PKCS#8 would be used if you need a way to identify the private key while using the binary construction. Basically it is a sequence of the key type followed by the key value. The key type consists of an algorithm identifier, which is encoded as an OID plus optional parameters. The original, and for a long time only, OID for an RSA key is defined in the PKCS#1 specifications:
The object identifier rsaEncryption identifies RSA public and private
keys as defined in Appendices A.1.1 and A.1.2. The parameters field
has associated with this OID in a value of type AlgorithmIdentifier
SHALL have a value of type NULL.
rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 }
Which means that the key is specified using 1.2.840.113549.1.1.1. Note that this doesn't indicate the algorithm to be used for that key. OTOH PKCS#1 (now) defines different OIDs for OAEP and PSS and their related parameters in that same appendix, and RFC4055 directs the use of those OIDs and parameters in public keys in PKIX certificates -- and 4055 is standards track while 8017 is not. [DaveT note: I suspect the statement about always using rsaEncryption is a leftover from v1 when it meant that the key didn't specify a signature hash like sha1withRSA.]
There is of course another reason to choose PKCS#8 and that's if you want to use a standard, documented, and (potentially) strong encryption for your private key. (PKCS#8 specifies the encryption with a very general AlgorithmIdentifier syntax, so it is possible to use a weak encryption algorithm, or a low and inadequate iteration count; however most software won't do so by default.) There is no official encryption method for a PKCS#1 private key, although OpenSSL (formerly SSLeay) -- and a huge number of things that have been developed to be compatible with OpenSSL -- uses an ad-hoc, PEM-based, and quite poor method (specifically for PBKDF it uses OpenSSL's EVP_BytesToKey function with ONE iteration of MD5; see numerous Qs on the crypto and security Stacks about how bad this is).
As indicated, PKCS#8 encoded information can be put within PEM headers. For the "inner" PKCS#8 structure the header "PRIVATE KEY" is used. For the encrypted "outer" structure the header "ENCRYPTED PRIVATE KEY" is used. (Both of these are in RFC7468, cited above.)
SPKI
SPKI is an acronym for SubjectPublicKeyInfo. It is the main method within the X.509/PKIX specification to describe a public key. It is almost identical to the "inner" PKCS#8 structure in the sense that it simply consist of a sequence of an algorithm identifier with the value of the public key. Usually the same algorithm identifier is even used for both the public and the private key. As with PKCS#8, the sole purpose is to be able to identify the key type.
These keys can be encoded within PEM, and they then would use "PUBLIC KEY" in the header analogous to "inner" PCKS#8.
X.509/PKIX
X.509 (or its Internet form, PKIX) specifies the certificate format used for instance for TLS, but also for CMS (the cryptographic message syntax originally specified in and still sometimes called PKCS#7) as well as S/MIME (the standard for secure email based on CMS) and many other protocols such as XMLenc and XMLdigsig but also code signing etc. etc. X.509 certificates can be used to create a PKI, a public key infrastructure. Certificates are the main method of distributing and trusting public keys. When creating a key pair, the public key is quite often simply stored within a certificate that also contains information about the holder of the certificate which can be a human, a "role" or system such as server.
For RSA to work it is usually required to not just have the public key but to establish trust in the public key. Otherwise you'd not know who's public key you would be using to verify a signature, or who you are encrypting data for. For that reason most protocols that have multiple entities must have some way of establishing the identity of those entities. Although there are other ways of establishing trust, X.509 is the most common hierarchical method of establishing trust, relying on trust of Certification Authorities to indicate trust of underlying parties and their certificates.
X.509 certificates are often encoded to text as well, which is unfortunately not directly indicated by the file extension (so a .cer, .crt, .cert or whatever can contain a binary encoding or textual encoding. Multiple (trusted) certificates are sometimes present in a single file as well. Certificates are indicated using the X.509
PKCS#12
PKCS#12 is what cryptographers usually call a container format. It contains a description of storing various cryptographic elements and, of course, a way of establishing what is stored and how to retrieve the information. PKCS#12 is is commonly used in two ways:
to store private keys with their certificate chain, starting with the certificate that contains the public key, followed by the certificate used to sign the certificate.
to store a set of trusted (CA) certificates so that certificate chains can be verified & validated.
Usually PKCS#12 files are used if a more secure method of storing these items such as the aforementioned hardware devices or key stores are not present. They offer protection by allowing the information including private keys and certificates to be encrypted using symmetric cryptography.

Related

In Public Key Cryptography how the server decrypts the message from client? [duplicate]

This question already has answers here:
Whose key is used to encrypt a HTTPS response?
(3 answers)
Closed 4 years ago.
In the Public Key Cryptography all I know is that the public key in the server is to encrypt the message and the client which has the private key can decrypt that message which is fine.
The part which I don't understand is that as the server has only the public key to encrypt the message how it would decrypt the response from the client. I believe that the public can't be used to decrypt the response from the client.
Also how the client encrypts a message to the server as the private key is only used for decrypting the message and not for encrypting.
Sorry for my ignorance. I have searched the internet and somehow the answers to these are eluding from me.
Any help would be greatly appreciated.
Thanks,
Mohamed
If a server has only a public key it cannot decrypt a message from a client.
One more time, with the important vocab words in bold: If a server has only a public key it cannot decrypt a message from a client.
What the server is probably doing is verifying a message signed by the client.
In the case of SSH public key authentication (RFC 4252, section 7) it is a signature over the just-negotiated session ID and some context data (which requires the client to have the private key). The server can then run the signature verification algorithm (which only requires the public key). If a preregistered key checks out, the client is thus authenticated.
In the case of RSA keys the signing and decrypting operations look mathematically similar, which can cause some to use the terms loosely, but we should be precise.
Encrypt (public key): Transform content in such a way to occlude it from everyone except the intended recipient (the holder of the private key).
Common algorithms: RSA
In encryption the encrypted output REPLACES the original content in transmission.
Public Key Encryption is frequently used to encrypt a newly generated symmetric key which actually encrypts the data. For RSA the encrypted output is limited by the key size, symmetric algorithms have much larger maxima.
Decrypt (private key): Transform content from the Encrypt operation back into its original form.
Since anyone could have your public key, anyone can encrypt data for you.
Nothing is inherent in the Encrypt/Decrypt pair to establish trust... the message could be a poison pill, and you don't know who wrote it.
Sign (private key): Apply a transform over an input (which is usually a digest/hash of the true content) to produce a value no one else can.
Common algorithms: RSA, ECDSA, DSA
The signature is presented WITH the content, it does not replace it.
Verify (public key): Apply a transform over the input and the signature which results in a true or false.
If the digest is computed independently by the content receiver the signature proves that the content was not tampered.
When the signature is deemed correct it proves that it was generated by the key holder, which can be used in a trust decision. (The key could have been compromised, in which case "key holder" and "original key holder" could be different)
For RSA this is "unpack the digest using an algorithm similar to decrypt, then compare the digests", so an RSA implementation could indicate what the correct hash is.
For DSA and ECDSA the digest is used as a BigInteger in a formula that produces the second half of the signature from the first half, so DSA can't tell you what a correct digest value is.

Asymmetric cryptography with reversed key roles

I'm trying to implement licensing system for a software to prevent piracy.
For this I need to read a license file within the application, and I need to make sure this file is written by the owner company.
Asymmetric cryptography has good potential for this aim, but in other way around!
Asymmetric cryptography algorithms, like RSA, give you a Public key and a Private key which are used as follow:
Private keys are used to decrypt.
Public keys are used to encrypt.
But I need them like this:
Private keys to be used to encrypt.
Public keys to be used to decrypt.
A simplistic idea would be to switch the role of public and private keys, but there are posts saying that in RSA public keys can be generated from private ones which make this idea impractical.
So here's my question: Is there any asymmetric cryptography with reversed key roles?
If speaking about RSA public/private key pair can be used in both cases you described. When you use private key to encrypt then public key decrypts and vice-versa.
As you said public key can be derived from private key but not the other way.
If you want to prove the origin of licensing file, use RSA in signature mode. In signature mode a hash is computed from the data you want to protect and then encrypted using private key. The result -the digital signature - is appended to the protected data.
Verification process starts by decrypting the signature which gives you the hash. Then compute hash value from the data. Computed and decrypted value shall be the same.
There are a lot of libraries providing comfortable way of signature creation and verification. You can choose depending on the platform you use for your application development.
http://en.wikipedia.org/wiki/Digital_signature

Can One Public Key be Used to Encrypt and Decrypt Data during the SSL Handshake?

When a server sends a Certificate message to a client, the public key in the server's certificate will be used to verify server’s identity(decryption with the public key).
The server follows its Certificate message with a ServerKeyExchange message, the session key information is signed using the same public key contained in the server’s certificate (encryption with the public key).
So I feel a Public key can be used to encrypt and decrypt data as well, am I right?
If yes, I wonder why text book just states one key(e.g. public key) is used to encrypt , and the other one(private key) is used to decrypt, rather than mention that a key can be used to both encrypt and decrypt?
[UPDATE2]
Really thanks for Bruno's help.
After reading Bruno's replies and RFC4346(section7.4.2 and 7.4.3) again and again, I suddenly felt I grasp the main points. :)
However, I am not sure I am right, and hope someone can confirm my following understanding. Thanks.
1.Server Certificate
SSL and TLS Essential section 3.6.1:
(SSL and TLS Essential: Securing the Web Author: Stephen A. Thomas)
...the public key in the server's certificate will only be used to verify its(server) identity.
Bruno wrote,
The public key in the server certificate isn't used to verify the server's identity itself.
I agree Bruno's viewpoint now, because a certificate is only a private-key-signed(encrypted) message that also contains someone else's(e.g., a client ) public key, so a client should use its trusted copy of the server's public key (usually, web browsers include dozens of these certificates in advance), instead of the public key in the server certificate, to verify the server's identity.
Is it right?
2.Server Key Exchange
SSL and TLS Essential section 3.6.2:
...the key information is signed using the public key contained in the server's certificate.
Bruno wrote,
Similarly, you don't really sign something with a public key. You only need one of the keys to sign, and that's the private key. You verify the signature with the matching public key.
...
"signing with a public key" is an unusual and misleading expression.
I think Bruno is right. The reasons are as follows,
RFC4346 section 7.4.2. Server Certificate
It MUST contain a key that matches the key exchange method, as follows.
Key Exchange Algorithm Certificate Key Type
RSA RSA public key; the certificate MUST
allow the key to be used for encryption.
DHE_DSS DSS public key.
DHE_RSA RSA public key that can be used for signing.
DH_DSS Diffie-Hellman key. The algorithm used
to sign the certificate MUST be DSS.
DH_RSA Diffie-Hellman key. The algorithm used
to sign the certificate MUST be RSA.
So the server sends one of 6 public key types in a certificate first.
RFC4346 section [7.4.3 Server Key Exchange Message][2]
>The server key exchange message is sent by the server.
>...
>This is true for the following key exchange methods:
>
DHE_DSS
DHE_RSA
DH_anon
>...
>This message conveys cryptographic information to allow the client to communicate the premaster secret.
The server chooses one of 3 key exchange methods, and uses its private key to sign(encrypt) cryptographic information.
When the client receives the encrypted cryptographic information, it will use the public key in ServerCertificate message to verify(decrypt) and get the plain-text cryptographic information.
Is it right?
In public key cryptography:
The private key is used for signing and deciphering/decrypting.
The public key is used for verifying signatures and enciphering/encrypting.
See the glossary of the TLS specification:
public key cryptography:
A class of cryptographic techniques employing two-key ciphers.
Messages encrypted with the public key can only be decrypted with
the associated private key. Conversely, messages signed with the
private key can be verified with the public key.
You cannot encrypt with a private key or decrypt with a public key, not for mathematical reasons, but because it doesn't make sense w.r.t. the definition of encrypt:
To convert ordinary language or other data into code; to hide
the meaning of a message by converting it into a form that
cannot be interpreted without knowing the secret method for
interpretation, called the key; to encode.
In a situation where you "encrypt with the private key", you effectively "scramble" the data indeed, but what's required to turn back the message into its original form is not a secret. Hence, it doesn't make sense to talk about encrypting in this context. Whether the mathematical operations behind it may work one way or the other doesn't matter at this stage.
Similarly, you don't really sign something with a public key. You only need one of the keys to sign, and that's the private key. You verify the signature with the matching public key.
It's quite common (even in the TLS specification) to say "signing with a certificate", when what's really implied is computing the signature with the private key matching the certificate. In many cases, not specifically TLS, the certificate itself is communicated along with the signature (whether-or-not one chooses to trust that certificate is another matter).
Expressions such as "using your certificate to authenticate" or "using your certificate to sign" are generally acceptable, so long as you understand that "certificate" is used there to shorten "certificate and its private key", and that it's in fact the private key that's necessary for those operations.
I don't have the book you're quoting, but this quote sounds misleading or incorrect (perhaps taken out of context here):
...the public key in the server's certificate will only be used to
verify its(server) identity.
The public key in the server certificate isn't used to verify the server's identity itself. What it does is ensuring that only someone/something with the corresponding private key will be able to decipher what you've encrypted with this public key: in this case (authenticated key exchange), the pre-master-secret which the server will prove it knows to the client by producing the correct Finished message, based on the pre-master-master it has managed to decipher.
The identity binding is done by the certificate itself, with is the signed combination of the public key, some identifiers (e.g. Subject DN and Subject Alternative Names) and possibly various other attributes (e.g. key usage, ...).
This side of the identity verification (i.e. checking who this certificate belongs to) is established by verifying the integrity of the certificate and that you trust what it says (usually PKI), and by verifying that the identity it belongs to is indeed the one you wanted to connect to (host name verification). This is done by verifying the certificate signature itself using a Certification Authority (CA) or by an outside mechanism, for example if you have explicitly granted an exception for a given certificate (possibly self-signed) using knowledge you have outside the scope of the PKI to which the certificate belongs. This step is rather independent of the TLS specification, although you'll need all these pieces together to make the communication secure.
There's a similar problem with this quote (again, possibly taken out of context):
...the key information is signed using the public key contained in the
server's certificate.
Although saying "signed with a certificate" is a common expression (as explained above), I'd say "signing using the public key" is definitely confusing, since "public key" is normally used in contrast to "private key", and it's really the private key that's used for signing. While even the TLS specification (Section F.1.1.2) talks about "signing with a certificate" in a few places, "signing with a public key" is an unusual and misleading expression.
I'm not sure whether "(decrypt)" and "(encrypt)" are in the book or your additions:
the public key in the server's certificate can be used to
verify(decrypt) the server's identity and sign(encrypt) the key
information(,then the client will use the key information to encrypt
pre_master_secret)
You actually verify you're talking to the actual server identified by that certificate because it's the only one capable of deciphering what you've encrypted with its public key (in the client key exchange message).
As it's put in the TLS specification Section F.1.1.2:
After verifying the server's certificate, the client encrypts a
pre_master_secret with the server's public key. By successfully
decoding the pre_master_secret and producing a correct finished
message, the server demonstrates that it knows the private key
corresponding to the server certificate.
What you're asking at the end doesn't completely make sense:
I know the public key can be used to verify server's
identity(Certificate message), but I can't understand the public key
why can be used to sign the key information, because the client
doesn't have the corresponding private key, how does the client verify
the key information?
The public key isn't used to verify the server's identity. You verify that you're talking to the server who has the private key matching the certificate it presented earlier by the fact it was able to decipher the pre-master-key and produce the correct finished message.
EDIT 2:
Following your edit, it seems that you're still using "sign(encrypt)" and "verify(decrypt)" as if encrypting was the same as signing and verifying was the same as decrypting. I would suggest once again that you stop making these associations: these are 4 distinct operations. While the maths may be the same when using RSA, this doesn't work for DSA, which is only a signature algorithm (so signing/verifying only).
When the client receives the encrypted cryptographic information, it
will use the public key in ServerCertificate message to
verify(decrypt) and get the plain-text cryptographic information.
The client doesn't receive any encrypted data during the handshake (only signed data).
For a better general understanding, you should start by trying to understand how Diffie-Hellman and its ephemeral variant (for DHE cipher suites) work.
(In practice, I wouldn't focus too much on non-ephemeral DH_RSA/DH_DSS cipher suites. To be honest, I'm not sure whether they're much used. I haven't seen any example of certificate with the necessary DH attributes, and these cipher suites are not in supported lists by OpenSSL or Java 7. DHE/EDH are much more common, and don't require special attributes in the certificate.)
If you use an RSA key exchange algorithm, the client will encrypt the pre-master-key in the client key exchange message; if it's using one of the DH key exchange algorithms, it will send its DH parameters so that client and server can agree on a pre-master-key (in this case, the client will have checked that the server's DH parameters come from the right server by verifying the signature of the server key exchange message sent beforehand). See description of the Client Key Exchange Message:
With this message, the premaster secret is set, either though
direct transmission of the RSA-encrypted secret or by the
transmission of Diffie-Hellman parameters that will allow each
side to agree upon the same premaster secret.
Regarding the other points:
a certificate is only a private-key-signed(encrypted) message that
also contains someone else's(e.g., a client ) public key, so a client
should use its trusted copy of the server's public key (usually, web
browsers include dozens of these certificates in advance), instead of
the public key in the server certificate, to verify the server's
identity.
Three things happen to verify you're talking to the right server:
The handshake itself, if successful, guarantees that you're talking to the server that has the private key for the certificate it has presented in the server certificate message. If using RSA key exchange, this is guaranteed by the fact it's the only one that can decipher what the client sent in the client key exchange message (since it's encrypted with the public key); if using an EDH key exchange, this is guaranteed because the server signed its DH parameters in the server key exchange message, verifiable with this public key.
The fact that you can verify the certificate itself. This is rather independent of how TLS works, but it's usually done using a PKI: the client has a pre-set list of trusted CA certificates, the public keys of which can be used to verify the signature in new certificates it doesn't already know about (such as the server certificate). Verifying that signature allows the client to bind that public key to an identifier (Subject DN and/or alt. name). This gives you the identity of the server to which the client is talking.
The host name verification: it's not good enough to know that you're talking to someone who's presented you a genuine ID that's valid for them, you also need to check that the name matches the server you intended to connect to.
When I said "The public key in the server certificate isn't used to verify the server's identity itself", I meant that the public key wasn't used to verify points 2 and 3. Point 1 guarantees you that you're talking to the server that has the private key matching the certificate it presented, but it doesn't tell you who this is. Verifying the identity of the server is is up to point 2, so as to be able to bind an identifier to that key/cert.
In a PPK algorithm like RSA, you have two different communication channels. Information encrypted using the public key is only readable to the possessor of the private key, and information encrypted using the private key is only readable to the possessor of the public key.
In fact, the selection of which half of the pair is "public" is completely arbitrary.
Now, in practice this doesn't much matter; the whole world has access to the public key, so encrypting something with the private part wouldn't do anything to secure it. But you can use this for authentication: since only one holder has the private key, if a message is validly encrypted using it, then the private-key holder must have been the author.
That's why your book doesn't say that the private key is used for encryption: because it's used for integrity, not for confidentiality, as any message sealed using it would be readable to anyone possessing the non-secret public half. While the integrity validation mechanism is technically encryption (it is encipherment using modular exponentiation), it would be confusing to mention this in a foundations-of-cryptography context as it's not what people think when they hear "encryption" - they think "privacy".
I had the same restlessness, since its difficult to ask without falling in technical holes. Quick, easy answer: regardless of the method details, yes, you could reverse engineer and decrypt from one key (is just math at the end) but because of the complexity of the operation, using a long value (you may use ie. a 4096-bit value) would make the reverse operation timeless, so you had to use either a machine so big that still doesnt exists or wait indefinitely, making it inviable... until someone comes up with a quick method to do it.
may want to take a look:
http://www.usna.edu/CS/si110arch/si110AY12F/lec/l29/lec.html

Save a SecKeyRef Asymmetric Key Pair to disk as a Certificate

I have created two SecKeyRef items via SecKeyGeneratePair, but now I would like to turn the public key into a x509 Digital Certificate – and/or both the public and private keys into a PKCS #12 (.p12) certificate – and save it to disk as a file. This way I can do whatever I need to with it, including sending the certificates to other services or computers.
I would prefer to not use the keychain, but even with that I am having some trouble finding good documentation on exactly how to create a certificate out of a pair of SecKeyRefs, and writing them out as a certificate file.
You want the Security Transforms Programming Guide. It covers most of what you need for this. Some parts (like SecItemExport) are not documented in the reference documentation, only in the public header files. But SecItemExport is the new 10.7 way to handle this stuff.

How do you save and retrieve a Key/IV pair securely?

I'm using VB.Net's RijndaelManaged (RM) to encrypt files, using the RM.GenerateKey and RM.GenerateIV methods to generate the Key and IV and encrypting the file using the CryptoStream class. I'm planning on saving this Key and IV to a file and want to make sure I'm doing it the right way. I am combining the IV+Key, and encrypting that with my RSA Public key and writing it out to a file. Then, to decrypt I use the RSA Private key on this file to get the IV+Key, split them up and set RM.Key and RM.IV to these values and run the decryptor.
Is this the best method to accomplish this, or is there a preferred method for saving the IV & Key?
That's the general idea. The IV does not need to be kept secret, however. Only the "secret key" is secret.
You might consider using a standard like S/MIME (or its underlying Cryptographic Message Syntax) for your file format. I'm not sure if Bouncycastle has ported their S/MIME (or PGP) libraries to .NET, or if .NET has S/MIME support built-in, but there is likely to be a free library available for your platform. A widely used open source library like this has probably been tested and scrutinized more closely than you'll be able to do yourself, and they implement protocols designed by experts in cryptography so your don't have to wonder what pitfalls you've overlooked.
The model you've described is similar to S/MIME's "KeyTransRecipientInfo" method for key exchange. A symmetric key is generated to encrypt the data, then that key is encrypted with the public key of each intended recipient. The encrypted key and the IV (which is not encrypted in this standard) are bundled with information about the algorithms used in a CMS structure. The encrypted data can be included in the same bundle, or be in an separate file.
PGP has mode that is an essentially equivalent.