diff options
author | lloyd <[email protected]> | 2010-06-15 04:53:05 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2010-06-15 04:53:05 +0000 |
commit | 165671b144884c8787cf2ccda4ef9799dfe47ccd (patch) | |
tree | bc685dcf3958b15d909ea10a3acb605ca6dea720 /doc | |
parent | 739ea28b60f9cdf4eb9fe9e37fc7c099e501c5b2 (diff) |
Update X509/PKCS8 docs WRT BER_encode
Diffstat (limited to 'doc')
-rw-r--r-- | doc/api.tex | 161 |
1 files changed, 60 insertions, 101 deletions
diff --git a/doc/api.tex b/doc/api.tex index 31e74c996..e4d4d5cb1 100644 --- a/doc/api.tex +++ b/doc/api.tex @@ -1225,7 +1225,7 @@ The interfaces for doing either of these are quite similar. Let's look at the X.509 stuff first: \begin{verbatim} namespace X509 { - void encode(const Public_Key& key, Pipe& out, X509_Encoding enc = PEM); + MemoryVector<byte> BER_encode(const Public_Key& key); std::string PEM_encode(const Public_Key& out); Public_Key* load_key(DataSource& in); @@ -1234,21 +1234,17 @@ namespace X509 { } \end{verbatim} -Basically, \function{X509::encode} will take an \type{Public\_Key} -(as of now, that's any RSA, DSA, or Diffie-Hellman key) and encodes it -using \arg{enc}, which can be either \type{PEM} or -\type{RAW\_BER}. Using \type{PEM} is \emph{highly} recommended for -many reasons, including compatibility with other software, for -transmission over 8-bit unclean channels, because it can be identified -by a human without special tools, and because it sometimes allows more -sane behavior of tools that process the data. It will place the -encoding into \arg{out}. Remember that if you have just created the -\type{Pipe} that you are passing to \function{X509::encode}, you need -to call \function{start\_msg} first. Particularly with public keys, -about 99\% of the time you just want to PEM encode the key and then -write it to a file or something. In this case, it's probably easier to -use \function{X509::PEM\_encode}. This function will simply return the -PEM encoding of the key as a \type{std::string}. +The function \function{X509::BER\_encode} will take any +\type{Public\_Key} and return a standard binary structure representing +the key which can be read by many other crypto libraries. + +The function \function{X509::PEM\_encode} does the same, but +additionally formats it into a text format with headers and base64 +encoding. Using PEM is \emph{highly} recommended for many reasons, +including compatibility with other software, for transmission over +8-bit unclean channels, because it can be identified by a human +without special tools, and because it sometimes allows more sane +behavior of tools that process the data. For loading a public key, the preferred method is one of the variants of \function{load\_key}. This function will return a newly allocated @@ -1257,12 +1253,12 @@ course, the source is in fact storing a representation of a public key). The encoding used (PEM or BER) need not be specified; the format will be detected automatically. The key is allocated with \function{new}, and should be released with \function{delete} when you -are done with it. The first takes a generic \type{DataSource} that -you have to allocate~--~the others are simple wrapper functions that -take either a filename or a memory buffer. +are done with it. The first takes a generic \type{DataSource} that you +have to allocate~--~the others are simple wrapper functions that take +either a filename or a memory buffer. So what can you do with the return value of \function{load\_key}? On -its own, a \type{X509\_PublicKey} isn't particularly useful; you can't +its own, a \type{Public\_Key} isn't particularly useful; you can't encrypt messages or verify signatures, or much else. But, using \function{dynamic\_cast}, you can figure out what kind of operations the key supports. Then, you can cast the key to the appropriate type @@ -1281,14 +1277,13 @@ and pass it to a higher-level class. For example: \subsubsection{Private Keys} -There are two different options for private key import/export. The first is a -plaintext version of the private key. This is supported by the following -functions: +There are two different options for private key import/export. The +first is a plaintext version of the private key. This is supported by +the following functions: \begin{verbatim} namespace PKCS8 { - void encode(const Private_Key& key, Pipe& to, X509_Encoding enc = PEM); - + SecureVector<byte> BER_encode(const Private_Key& key); std::string PEM_encode(const Private_Key& key); } \end{verbatim} @@ -1304,60 +1299,39 @@ use the versions that encrypt the key based on a passphrase. For importing, the same functions can be used for encrypted and unencrypted keys. -The other way to export a PKCS \#8 key is to first encode it in the same manner -as done above, then encrypt it (using a passphrase and the techniques of PKCS -\#5), and store the whole thing into another structure. This method is -definitely preferred, since otherwise the private key is unprotected. The -following functions support this technique: +The other way to export a PKCS \#8 key is to first encode it in the +same manner as done above, then encrypt it (using a passphrase and the +techniques of PKCS \#5), and store the whole thing into another +structure. This method is definitely preferred, since otherwise the +private key is unprotected. The following functions support this +technique: \begin{verbatim} namespace PKCS8 { - void encrypt_key(const Private_Key& key, Pipe& out, - std::string passphrase, std::string pbe = "", - X509_Encoding enc = PEM); - std::string PEM_encode(const Private_Key& key, std::string passphrase, - std::string pbe = ""); -} + SecureVector<byte> BER_encode(const Private_Key& key, + RandomNumberGenerator& rng, + const std::string& pass, + const std::string& pbe_algo = ""); + + std::string PEM_encode(const Private_Key& key, + RandomNumberGenerator& rng, + const std::string& pass, + const std::string& pbe_algo = ""); \end{verbatim} -To export an encrypted private key, call \function{PKCS8::encrypt\_key}. The -\arg{key}, \arg{out}, and \arg{enc} arguments are similar in usage to the ones -for \function{PKCS8::encode}. As you might notice, there are two new arguments -for \function{PKCS8::encrypt\_key}, however. The first is a passphrase (which -you presumably got from a user somehow). This will be used to encrypt the key. -The second new argument is \arg{pbe}; this specifies a particular password -based encryption (or PBE) algorithm. - -The \function{PEM\_encode} version shown here is similar to the one that -doesn't take a passphrase. Essentially it encrypts the key (using the default -PBE algorithm), and then returns a C++ string with the PEM encoding of the key. - -If \arg{pbe} is blank, then the default algorithm (controlled by the -``base/default\_pbe'' option) will be used. As shipped, this default is -``PBE-PKCS5v20(SHA-1,TripleDES/CBC)'' . This is among the more secure options -of PKCS \#5, and is widely supported among implementations of PKCS \#5 v2.0. It -offers 168 bits of security against attacks, which should be more that -sufficient. If you need compatibility with systems that only support PKCS \#5 -v1.5, pass ``PBE-PKCS5v15(MD5,DES/CBC)'' as \arg{pbe}. However, be warned that -this PBE algorithm only has 56 bits of security against brute force attacks. As -of 1.4.5, all three keylengths of AES are also available as options, which can -be used with by specifying a PBE algorithm of -``PBE-PKCS5v20(SHA-1,AES-256/CBC)'' (or ``AES-128'' or ``AES-192''). Support -for AES is slightly non-standard, and some applications or libraries might not -handle it. It is known that OpenSSL (0.9.7 and later) do handle AES for private -key encryption. - -There may be some strange programs out there that support the v2.0 extensions -to PBES1 but not PBES2; if you need to inter-operate with a program like that, -use ``PBE-PKCS5v15(MD5,RC2/CBC)''. For example, OpenSSL supports this format -(though since it also supports the v2.0 schemes, there is no reason not to just -use TripleDES or AES). This scheme uses a 64-bit key that, while -significantly better than a 56-bit key, is a bit too small for comfort. - -Last but not least, there are some functions that are basically identical to -\function{X509::load\_key} that will load, and possibly decrypt, a PKCS \#8 -private key: +There are three new arguments needed here to support the encryption +process in addition to the private key itself. The first is a +\type{RandomNumberGenerator}, which is needed for various purposes +internally. The \arg{pass} argument is the passphrase that will be +used to encrypt the key. Both of these are required. The final +(optional) argument is \arg{pbe}; this specifies a particular password +based encryption (or PBE) algorithm. If you don't specify a PBE, +a compiled in default will be used; this should be fine. + +Last but not least, there are some functions that are basically +identical to \function{X509::load\_key} that will load, and possibly +decrypt, a PKCS \#8 private key: \begin{verbatim} namespace PKCS8 { @@ -1396,25 +1370,9 @@ the versions taking the \type{std::string}. All versions need access to a \type{RandomNumberGenerator} in order to perform probabilistic tests on the loaded key material. -After loading a key, you can use \function{dynamic\_cast} to find out what -operations it supports, and use it appropriately. Remember to \function{delete} -it once you are done with it. - -\subsubsection{Limitations} - -As of now Nyberg-Rueppel and Rabin-Williams keys cannot be imported or -exported, because they have no official ASN.1 OID or definition. ElGamal keys -can (as of Botan 1.3.8) be imported and exported, but the only other -implementation that supports the format is Peter Gutmann's Cryptlib. If you -can help it, stick to RSA and DSA. - -\emph{Note}: Currently NR and RW are given basic ASN.1 key formats (which -mirror DSA and RSA, respectively), which means that, if they are assigned an -OID, they can be imported and exported just as easily as RSA and DSA. You can -assign them an OID by putting a line in a Botan configuration file, calling -\function{OIDS::add\_oid}, or editing \filename{src/policy.cpp}. Be warned that -it is possible that a future version will use a format that is different from -the current one (\ie, a newly standardized format). +After loading a key, you can use \function{dynamic\_cast} to find out +what operations it supports, and use it appropriately. Remember to +\function{delete} it once you are done with it. \pagebreak \section{Certificate Handling} @@ -1444,15 +1402,16 @@ definitions of various common ASN.1 constructs used in X.509). \subsection{So what's in an X.509 certificate?} -Obviously, you want to be able to get the public key. This is achieved by -calling the member function \function{subject\_public\_key}, which will return -a \type{X509\_PublicKey*}. As to what to do with this, read about -\function{load\_key} in the section ``Importing and Exporting PK Keys''. In the -general case, this could be any kind of public key, though 99\% of the time it -will be an RSA key. However, Diffie-Hellman and DSA keys are also supported, so -be careful about how you treat this. It is also a wise idea to examine the -value returned by \function{constraints}, to see what uses the public key is -approved for. +Obviously, you want to be able to get the public key. This is achieved +by calling the member function \function{subject\_public\_key}, which +will return a \type{Public\_Key*}. As to what to do with this, read +about \function{load\_key} in the section ``Importing and Exporting PK +Keys''. In the general case, this could be any kind of public key, +though 99\% of the time it will be an RSA key. However, Diffie-Hellman +and DSA keys are also supported, so be careful about how you treat +this. It is also a wise idea to examine the value returned by +\function{constraints}, to see what uses the public key is approved +for. The second major piece of information you'll want is the name/email/etc of the person to whom this certificate is assigned. Here is where things get a little |