From 1b0f06037e00d426f37c9180f02f1ec2157644bd Mon Sep 17 00:00:00 2001
From: lloyd <lloyd@randombit.net>
Date: Thu, 4 Mar 2010 02:22:02 +0000
Subject: The code in pk_codecs was actually entirely tied to the code in
 pubkey; you literally could not compile any pubkey code without it. Move it
 up to the pubkey dir, it wasn't at all useful to have it in its own dir.

---
 src/cert/cvc/info.txt             |   1 -
 src/cert/x509/info.txt            |   1 -
 src/cms/info.txt                  |   2 +-
 src/pubkey/dl_algo/info.txt       |   1 -
 src/pubkey/ecc_key/info.txt       |   1 -
 src/pubkey/if_algo/info.txt       |   1 -
 src/pubkey/info.txt               |   6 +
 src/pubkey/pk_codecs/info.txt     |   7 -
 src/pubkey/pk_codecs/pkcs8.cpp    | 309 --------------------------------------
 src/pubkey/pk_codecs/pkcs8.h      | 153 -------------------
 src/pubkey/pk_codecs/x509_key.cpp | 172 ---------------------
 src/pubkey/pk_codecs/x509_key.h   |  99 ------------
 src/pubkey/pkcs8.cpp              | 309 ++++++++++++++++++++++++++++++++++++++
 src/pubkey/pkcs8.h                | 153 +++++++++++++++++++
 src/pubkey/x509_key.cpp           | 172 +++++++++++++++++++++
 src/pubkey/x509_key.h             |  99 ++++++++++++
 16 files changed, 740 insertions(+), 746 deletions(-)
 delete mode 100644 src/pubkey/pk_codecs/info.txt
 delete mode 100644 src/pubkey/pk_codecs/pkcs8.cpp
 delete mode 100644 src/pubkey/pk_codecs/pkcs8.h
 delete mode 100644 src/pubkey/pk_codecs/x509_key.cpp
 delete mode 100644 src/pubkey/pk_codecs/x509_key.h
 create mode 100644 src/pubkey/pkcs8.cpp
 create mode 100644 src/pubkey/pkcs8.h
 create mode 100644 src/pubkey/x509_key.cpp
 create mode 100644 src/pubkey/x509_key.h

diff --git a/src/cert/cvc/info.txt b/src/cert/cvc/info.txt
index f2894297b..0d5687770 100644
--- a/src/cert/cvc/info.txt
+++ b/src/cert/cvc/info.txt
@@ -33,7 +33,6 @@ filters
 libstate
 oid_lookup
 pem
-pk_codecs
 pubkey
 x509
 </requires>
diff --git a/src/cert/x509/info.txt b/src/cert/x509/info.txt
index a5cd973a4..510163e69 100644
--- a/src/cert/x509/info.txt
+++ b/src/cert/x509/info.txt
@@ -39,7 +39,6 @@ filters
 libstate
 oid_lookup
 pem
-pk_codecs
 pubkey
 rng
 sha1
diff --git a/src/cms/info.txt b/src/cms/info.txt
index 44c5811f8..b863a9a26 100644
--- a/src/cms/info.txt
+++ b/src/cms/info.txt
@@ -9,7 +9,7 @@ hash
 libstate
 oid_lookup
 pem
-pk_codecs
+pubkey
 sha1
 sym_algo
 x509
diff --git a/src/pubkey/dl_algo/info.txt b/src/pubkey/dl_algo/info.txt
index 21829fa42..f6e609062 100644
--- a/src/pubkey/dl_algo/info.txt
+++ b/src/pubkey/dl_algo/info.txt
@@ -4,6 +4,5 @@ define DL_PUBLIC_KEY_FAMILY
 asn1
 dl_group
 numbertheory
-pk_codecs
 rng
 </requires>
diff --git a/src/pubkey/ecc_key/info.txt b/src/pubkey/ecc_key/info.txt
index 4650fb612..e08a4231d 100644
--- a/src/pubkey/ecc_key/info.txt
+++ b/src/pubkey/ecc_key/info.txt
@@ -6,5 +6,4 @@ asn1
 bigint
 ec_dompar
 numbertheory
-pk_codecs
 </requires>
diff --git a/src/pubkey/if_algo/info.txt b/src/pubkey/if_algo/info.txt
index 833117819..c0914cd15 100644
--- a/src/pubkey/if_algo/info.txt
+++ b/src/pubkey/if_algo/info.txt
@@ -19,5 +19,4 @@ asn1
 bigint
 libstate
 numbertheory
-pk_codecs
 </requires>
diff --git a/src/pubkey/info.txt b/src/pubkey/info.txt
index b28bd1868..4d7105e9d 100644
--- a/src/pubkey/info.txt
+++ b/src/pubkey/info.txt
@@ -3,15 +3,19 @@ define PUBLIC_KEY_CRYPTO
 <source>
 pk_algs.cpp
 pk_keys.cpp
+pkcs8.cpp
 pubkey.cpp
 pubkey_enums.cpp
 workfactor.cpp
+x509_key.cpp
 </source>
 
 <header:public>
 pk_keys.h
+pkcs8.h
 pubkey.h
 pubkey_enums.h
+x509_key.h
 </header:public>
 
 <header:internal>
@@ -26,6 +30,8 @@ bigint
 filters
 kdf
 oid_lookup
+pbe
+pem
 pk_pad
 rng
 sym_algo
diff --git a/src/pubkey/pk_codecs/info.txt b/src/pubkey/pk_codecs/info.txt
deleted file mode 100644
index 64fb10b8a..000000000
--- a/src/pubkey/pk_codecs/info.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-<requires>
-asn1
-filters
-oid_lookup
-pbe
-pem
-</requires>
diff --git a/src/pubkey/pk_codecs/pkcs8.cpp b/src/pubkey/pk_codecs/pkcs8.cpp
deleted file mode 100644
index 099d52ffa..000000000
--- a/src/pubkey/pk_codecs/pkcs8.cpp
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
-* PKCS #8
-* (C) 1999-2008 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/pkcs8.h>
-#include <botan/get_pbe.h>
-#include <botan/der_enc.h>
-#include <botan/ber_dec.h>
-#include <botan/asn1_obj.h>
-#include <botan/oids.h>
-#include <botan/pem.h>
-#include <botan/internal/pk_algs.h>
-#include <memory>
-
-namespace Botan {
-
-namespace PKCS8 {
-
-namespace {
-
-/*
-* Get info from an EncryptedPrivateKeyInfo
-*/
-SecureVector<byte> PKCS8_extract(DataSource& source,
-                                 AlgorithmIdentifier& pbe_alg_id)
-   {
-   SecureVector<byte> key_data;
-
-   BER_Decoder(source)
-      .start_cons(SEQUENCE)
-         .decode(pbe_alg_id)
-         .decode(key_data, OCTET_STRING)
-      .verify_end();
-
-   return key_data;
-   }
-
-/*
-* PEM decode and/or decrypt a private key
-*/
-SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui,
-                                AlgorithmIdentifier& pk_alg_id)
-   {
-   AlgorithmIdentifier pbe_alg_id;
-   SecureVector<byte> key_data, key;
-   bool is_encrypted = true;
-
-   try {
-      if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
-         key_data = PKCS8_extract(source, pbe_alg_id);
-      else
-         {
-         std::string label;
-         key_data = PEM_Code::decode(source, label);
-         if(label == "PRIVATE KEY")
-            is_encrypted = false;
-         else if(label == "ENCRYPTED PRIVATE KEY")
-            {
-            DataSource_Memory key_source(key_data);
-            key_data = PKCS8_extract(key_source, pbe_alg_id);
-            }
-         else
-            throw PKCS8_Exception("Unknown PEM label " + label);
-         }
-
-      if(key_data.empty())
-         throw PKCS8_Exception("No key data found");
-      }
-   catch(Decoding_Error)
-      {
-      throw Decoding_Error("PKCS #8 private key decoding failed");
-      }
-
-   if(!is_encrypted)
-      key = key_data;
-
-   const u32bit MAX_TRIES = 3;
-
-   u32bit tries = 0;
-   while(true)
-      {
-      try {
-         if(MAX_TRIES && tries >= MAX_TRIES)
-            break;
-
-         if(is_encrypted)
-            {
-            DataSource_Memory params(pbe_alg_id.parameters);
-            std::auto_ptr<PBE> pbe(get_pbe(pbe_alg_id.oid, params));
-
-            User_Interface::UI_Result result = User_Interface::OK;
-            const std::string passphrase =
-               ui.get_passphrase("PKCS #8 private key", source.id(), result);
-
-            if(result == User_Interface::CANCEL_ACTION)
-               break;
-
-            pbe->set_key(passphrase);
-            Pipe decryptor(pbe.release());
-
-            decryptor.process_msg(key_data, key_data.size());
-            key = decryptor.read_all();
-            }
-
-         u32bit version;
-
-         BER_Decoder(key)
-            .start_cons(SEQUENCE)
-               .decode(version)
-               .decode(pk_alg_id)
-               .decode(key, OCTET_STRING)
-               .discard_remaining()
-            .end_cons();
-
-         if(version != 0)
-            throw Decoding_Error("PKCS #8: Unknown version number");
-
-         break;
-         }
-      catch(Decoding_Error)
-         {
-         ++tries;
-         }
-      }
-
-   if(key.empty())
-      throw Decoding_Error("PKCS #8 private key decoding failed");
-   return key;
-   }
-
-}
-
-/*
-* DER or PEM encode a PKCS #8 private key
-*/
-void encode(const Private_Key& key, Pipe& pipe, X509_Encoding encoding)
-   {
-   const u32bit PKCS8_VERSION = 0;
-
-   SecureVector<byte> contents =
-      DER_Encoder()
-         .start_cons(SEQUENCE)
-            .encode(PKCS8_VERSION)
-            .encode(key.algorithm_identifier())
-            .encode(key.pkcs8_private_key(), OCTET_STRING)
-         .end_cons()
-      .get_contents();
-
-   if(encoding == PEM)
-      pipe.write(PEM_Code::encode(contents, "PRIVATE KEY"));
-   else
-      pipe.write(contents);
-   }
-
-/*
-* Encode and encrypt a PKCS #8 private key
-*/
-void encrypt_key(const Private_Key& key,
-                 Pipe& pipe,
-                 RandomNumberGenerator& rng,
-                 const std::string& pass, const std::string& pbe_algo,
-                 X509_Encoding encoding)
-   {
-   const std::string DEFAULT_PBE = "PBE-PKCS5v20(SHA-1,AES-128/CBC)";
-
-   Pipe raw_key;
-   raw_key.start_msg();
-   encode(key, raw_key, RAW_BER);
-   raw_key.end_msg();
-
-   std::auto_ptr<PBE> pbe(get_pbe(((pbe_algo != "") ? pbe_algo : DEFAULT_PBE)));
-
-   pbe->new_params(rng);
-   pbe->set_key(pass);
-
-   AlgorithmIdentifier pbe_algid(pbe->get_oid(), pbe->encode_params());
-
-   Pipe key_encrytor(pbe.release());
-   key_encrytor.process_msg(raw_key);
-
-   SecureVector<byte> enc_key =
-      DER_Encoder()
-         .start_cons(SEQUENCE)
-            .encode(pbe_algid)
-            .encode(key_encrytor.read_all(), OCTET_STRING)
-         .end_cons()
-      .get_contents();
-
-   if(encoding == PEM)
-      pipe.write(PEM_Code::encode(enc_key, "ENCRYPTED PRIVATE KEY"));
-   else
-      pipe.write(enc_key);
-   }
-
-/*
-* PEM encode a PKCS #8 private key
-*/
-std::string PEM_encode(const Private_Key& key)
-   {
-   Pipe pem;
-   pem.start_msg();
-   encode(key, pem, PEM);
-   pem.end_msg();
-   return pem.read_all_as_string();
-   }
-
-/*
-* Encrypt and PEM encode a PKCS #8 private key
-*/
-std::string PEM_encode(const Private_Key& key,
-                       RandomNumberGenerator& rng,
-                       const std::string& pass,
-                       const std::string& pbe_algo)
-   {
-   if(pass == "")
-      return PEM_encode(key);
-
-   Pipe pem;
-   pem.start_msg();
-   encrypt_key(key, pem, rng, pass, pbe_algo, PEM);
-   pem.end_msg();
-   return pem.read_all_as_string();
-   }
-
-/*
-* Extract a private key and return it
-*/
-Private_Key* load_key(DataSource& source,
-                      RandomNumberGenerator& rng,
-                      const User_Interface& ui)
-   {
-   AlgorithmIdentifier alg_id;
-   SecureVector<byte> pkcs8_key = PKCS8_decode(source, ui, alg_id);
-
-   const std::string alg_name = OIDS::lookup(alg_id.oid);
-   if(alg_name == "" || alg_name == alg_id.oid.as_string())
-      throw PKCS8_Exception("Unknown algorithm OID: " +
-                            alg_id.oid.as_string());
-
-   std::auto_ptr<Private_Key> key(get_private_key(alg_name));
-
-   if(!key.get())
-      throw PKCS8_Exception("Unknown PK algorithm/OID: " + alg_name + ", " +
-                           alg_id.oid.as_string());
-
-   std::auto_ptr<PKCS8_Decoder> decoder(key->pkcs8_decoder(rng));
-
-   if(!decoder.get())
-      throw Decoding_Error("Key does not support PKCS #8 decoding");
-
-   decoder->alg_id(alg_id);
-   decoder->key_bits(pkcs8_key);
-
-   return key.release();
-   }
-
-/*
-* Extract a private key and return it
-*/
-Private_Key* load_key(const std::string& fsname,
-                      RandomNumberGenerator& rng,
-                      const User_Interface& ui)
-   {
-   DataSource_Stream source(fsname, true);
-   return PKCS8::load_key(source, rng, ui);
-   }
-
-/*
-* Extract a private key and return it
-*/
-Private_Key* load_key(DataSource& source,
-                      RandomNumberGenerator& rng,
-                      const std::string& pass)
-   {
-   return PKCS8::load_key(source, rng, User_Interface(pass));
-   }
-
-/*
-* Extract a private key and return it
-*/
-Private_Key* load_key(const std::string& fsname,
-                      RandomNumberGenerator& rng,
-                      const std::string& pass)
-   {
-   return PKCS8::load_key(fsname, rng, User_Interface(pass));
-   }
-
-/*
-* Make a copy of this private key
-*/
-Private_Key* copy_key(const Private_Key& key,
-                      RandomNumberGenerator& rng)
-   {
-   Pipe bits;
-
-   bits.start_msg();
-   PKCS8::encode(key, bits);
-   bits.end_msg();
-
-   DataSource_Memory source(bits.read_all());
-   return PKCS8::load_key(source, rng);
-   }
-
-}
-
-}
diff --git a/src/pubkey/pk_codecs/pkcs8.h b/src/pubkey/pk_codecs/pkcs8.h
deleted file mode 100644
index 9488c2c0b..000000000
--- a/src/pubkey/pk_codecs/pkcs8.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
-* PKCS #8
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_PKCS8_H__
-#define BOTAN_PKCS8_H__
-
-#include <botan/x509_key.h>
-#include <botan/ui.h>
-
-namespace Botan {
-
-/*
-* PKCS #8 Private Key Decoder
-*/
-class BOTAN_DLL PKCS8_Decoder
-   {
-   public:
-      /**
-      * Set the algorithm identifier associated with the scheme
-      * this decoders key is part of.
-      * @param alg_id the algorithm identifier
-      */
-      virtual void alg_id(const AlgorithmIdentifier&) = 0;
-
-      /**
-      * Set the DER encoded key.
-      * @param key the DER encoded key
-      */
-      virtual void key_bits(const MemoryRegion<byte>&) = 0;
-      virtual ~PKCS8_Decoder() {}
-   };
-
-/**
-* PKCS #8 General Exception
-*/
-struct BOTAN_DLL PKCS8_Exception : public Decoding_Error
-   {
-   PKCS8_Exception(const std::string& error) :
-      Decoding_Error("PKCS #8: " + error) {}
-   };
-
-namespace PKCS8 {
-
-/**
-* Encode a private key into a pipe.
-* @param key the private key to encode
-* @param pipe the pipe to feed the encoded key into
-* @param enc the encoding type to use
-*/
-BOTAN_DLL void encode(const Private_Key& key, Pipe& pipe,
-                      X509_Encoding enc = PEM);
-
-/**
-* Encode and encrypt a private key into a pipe.
-* @param key the private key to encode
-* @param pipe the pipe to feed the encoded key into
-* @param pass the password to use for encryption
-* @param rng the rng to use
-* @param pbe_algo the name of the desired password-based encryption algorithm;
-         if empty ("") a reasonable (portable/secure) default will be chosen.
-* @param enc the encoding type to use
-*/
-BOTAN_DLL void encrypt_key(const Private_Key& key,
-                           Pipe& pipe,
-                           RandomNumberGenerator& rng,
-                           const std::string& pass,
-                           const std::string& pbe_algo = "",
-                           X509_Encoding enc = PEM);
-
-
-/**
-* Get a string containing a PEM encoded private key.
-* @param key the key to encode
-* @return the encoded key
-*/
-BOTAN_DLL std::string PEM_encode(const Private_Key& key);
-
-/**
-* Get a string containing a PEM encoded private key, encrypting it with a
-* password.
-* @param key the key to encode
-* @param rng the rng to use
-* @param pass the password to use for encryption
-* @param pbe_algo the name of the desired password-based encryption algorithm;
-         if empty ("") a reasonable (portable/secure) default will be chosen.
-*/
-BOTAN_DLL std::string PEM_encode(const Private_Key& key,
-                                 RandomNumberGenerator& rng,
-                                 const std::string& pass,
-                                 const std::string& pbe_algo = "");
-
-/**
-* Load a key from a data source.
-* @param source the data source providing the encoded key
-* @param rng the rng to use
-* @param ui the user interface to be used for passphrase dialog
-* @return the loaded private key object
-*/
-BOTAN_DLL Private_Key* load_key(DataSource& source,
-                                RandomNumberGenerator& rng,
-                                const User_Interface& ui);
-
-/** Load a key from a data source.
-* @param source the data source providing the encoded key
-* @param rng the rng to use
-* @param pass the passphrase to decrypt the key. Provide an empty
-* string if the key is not encoded.
-* @return the loaded private key object
-*/
-BOTAN_DLL Private_Key* load_key(DataSource& source,
-                                RandomNumberGenerator& rng,
-                                const std::string& pass = "");
-
-/**
-* Load a key from a file.
-* @param filename the path to the file containing the encoded key
-* @param rng the rng to use
-* @param ui the user interface to be used for passphrase dialog
-* @return the loaded private key object
-*/
-BOTAN_DLL Private_Key* load_key(const std::string& filename,
-                                RandomNumberGenerator& rng,
-                                const User_Interface& ui);
-
-/** Load a key from a file.
-* @param filename the path to the file containing the encoded key
-* @param rng the rng to use
-* @param pass the passphrase to decrypt the key. Provide an empty
-* string if the key is not encoded.
-* @return the loaded private key object
-*/
-BOTAN_DLL Private_Key* load_key(const std::string& filename,
-                                RandomNumberGenerator& rng,
-                                const std::string& pass = "");
-
-/**
-* Copy an existing encoded key object.
-* @param key the key to copy
-* @param rng the rng to use
-* @return the new copy of the key
-*/
-BOTAN_DLL Private_Key* copy_key(const Private_Key& key,
-                                RandomNumberGenerator& rng);
-
-}
-
-}
-
-#endif
diff --git a/src/pubkey/pk_codecs/x509_key.cpp b/src/pubkey/pk_codecs/x509_key.cpp
deleted file mode 100644
index fdcfccf87..000000000
--- a/src/pubkey/pk_codecs/x509_key.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
-* X.509 Public Key
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/x509_key.h>
-#include <botan/filters.h>
-#include <botan/asn1_obj.h>
-#include <botan/der_enc.h>
-#include <botan/ber_dec.h>
-#include <botan/oids.h>
-#include <botan/pem.h>
-#include <botan/internal/pk_algs.h>
-#include <memory>
-
-namespace Botan {
-
-namespace X509 {
-
-/*
-* DER or PEM encode a X.509 public key
-*/
-void encode(const Public_Key& key, Pipe& pipe, X509_Encoding encoding)
-   {
-   MemoryVector<byte> der =
-      DER_Encoder()
-         .start_cons(SEQUENCE)
-            .encode(key.algorithm_identifier())
-            .encode(key.x509_subject_public_key(), BIT_STRING)
-         .end_cons()
-      .get_contents();
-
-   if(encoding == PEM)
-      pipe.write(PEM_Code::encode(der, "PUBLIC KEY"));
-   else
-      pipe.write(der);
-   }
-
-/*
-* PEM encode a X.509 public key
-*/
-std::string PEM_encode(const Public_Key& key)
-   {
-   Pipe pem;
-   pem.start_msg();
-   encode(key, pem, PEM);
-   pem.end_msg();
-   return pem.read_all_as_string();
-   }
-
-/*
-* Extract a public key and return it
-*/
-Public_Key* load_key(DataSource& source)
-   {
-   try {
-      AlgorithmIdentifier alg_id;
-      MemoryVector<byte> key_bits;
-
-      if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
-         {
-         BER_Decoder(source)
-            .start_cons(SEQUENCE)
-            .decode(alg_id)
-            .decode(key_bits, BIT_STRING)
-            .verify_end()
-         .end_cons();
-         }
-      else
-         {
-         DataSource_Memory ber(
-            PEM_Code::decode_check_label(source, "PUBLIC KEY")
-            );
-
-         BER_Decoder(ber)
-            .start_cons(SEQUENCE)
-            .decode(alg_id)
-            .decode(key_bits, BIT_STRING)
-            .verify_end()
-         .end_cons();
-         }
-
-      if(key_bits.empty())
-         throw Decoding_Error("X.509 public key decoding failed");
-
-      const std::string alg_name = OIDS::lookup(alg_id.oid);
-      if(alg_name == "")
-         throw Decoding_Error("Unknown algorithm OID: " +
-                              alg_id.oid.as_string());
-
-      std::auto_ptr<Public_Key> key_obj(get_public_key(alg_name));
-      if(!key_obj.get())
-         throw Decoding_Error("Unknown PK algorithm/OID: " + alg_name + ", " +
-                              alg_id.oid.as_string());
-
-      std::auto_ptr<X509_Decoder> decoder(key_obj->x509_decoder());
-
-      if(!decoder.get())
-         throw Decoding_Error("Key does not support X.509 decoding");
-
-      decoder->alg_id(alg_id);
-      decoder->key_bits(key_bits);
-
-      return key_obj.release();
-      }
-   catch(Decoding_Error)
-      {
-      throw Decoding_Error("X.509 public key decoding failed");
-      }
-   }
-
-/*
-* Extract a public key and return it
-*/
-Public_Key* load_key(const std::string& fsname)
-   {
-   DataSource_Stream source(fsname, true);
-   return X509::load_key(source);
-   }
-
-/*
-* Extract a public key and return it
-*/
-Public_Key* load_key(const MemoryRegion<byte>& mem)
-   {
-   DataSource_Memory source(mem);
-   return X509::load_key(source);
-   }
-
-/*
-* Make a copy of this public key
-*/
-Public_Key* copy_key(const Public_Key& key)
-   {
-   Pipe bits;
-   bits.start_msg();
-   X509::encode(key, bits, RAW_BER);
-   bits.end_msg();
-   DataSource_Memory source(bits.read_all());
-   return X509::load_key(source);
-   }
-
-/*
-* Find the allowable key constraints
-*/
-Key_Constraints find_constraints(const Public_Key& pub_key,
-                                 Key_Constraints limits)
-   {
-   const Public_Key* key = &pub_key;
-   u32bit constraints = 0;
-
-   if(dynamic_cast<const PK_Encrypting_Key*>(key))
-      constraints |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT;
-
-   if(dynamic_cast<const PK_Key_Agreement_Key*>(key))
-      constraints |= KEY_AGREEMENT;
-
-   if(dynamic_cast<const PK_Verifying_wo_MR_Key*>(key) ||
-      dynamic_cast<const PK_Verifying_with_MR_Key*>(key))
-      constraints |= DIGITAL_SIGNATURE | NON_REPUDIATION;
-
-   if(limits)
-      constraints &= limits;
-
-   return Key_Constraints(constraints);
-   }
-
-}
-
-}
diff --git a/src/pubkey/pk_codecs/x509_key.h b/src/pubkey/pk_codecs/x509_key.h
deleted file mode 100644
index a8f5267d7..000000000
--- a/src/pubkey/pk_codecs/x509_key.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
-* X.509 Public Key
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_X509_PUBLIC_KEY_H__
-#define BOTAN_X509_PUBLIC_KEY_H__
-
-#include <botan/pipe.h>
-#include <botan/pk_keys.h>
-#include <botan/alg_id.h>
-#include <botan/pubkey_enums.h>
-
-namespace Botan {
-
-/**
-* This class represents abstract X.509 public key decoders.
-*/
-class BOTAN_DLL X509_Decoder
-   {
-   public:
-      virtual void alg_id(const AlgorithmIdentifier&) = 0;
-      virtual void key_bits(const MemoryRegion<byte>&) = 0;
-      virtual ~X509_Decoder() {}
-   };
-
-/**
-* This namespace contains functions for handling X509 objects.
-*/
-namespace X509 {
-
-/*
-* X.509 Public Key Encoding/Decoding
-*/
-
-/**
-* Encode a key into a pipe.
-* @param key the public key to encode
-* @param pipe the pipe to feed the encoded key into
-* @param enc the encoding type to use
-*/
-BOTAN_DLL void encode(const Public_Key& key, Pipe& pipe,
-                      X509_Encoding enc = PEM);
-
-/**
-* PEM encode a public key into a string.
-* @param key the key to encode
-* @return the PEM encoded key
-*/
-BOTAN_DLL std::string PEM_encode(const Public_Key& key);
-
-/**
-* Create a public key from a data source.
-* @param source the source providing the DER or PEM encoded key
-* @return the new public key object
-*/
-BOTAN_DLL Public_Key* load_key(DataSource& source);
-
-/**
-* Create a public key from a string.
-* @param enc the string containing the PEM encoded key
-* @return the new public key object
-*/
-BOTAN_DLL Public_Key* load_key(const std::string& enc);
-
-/**
-* Create a public key from a memory region.
-* @param enc the memory region containing the DER or PEM encoded key
-* @return the new public key object
-*/
-BOTAN_DLL Public_Key* load_key(const MemoryRegion<byte>& enc);
-
-/**
-* Copy a key.
-* @param key the public key to copy
-* @return the new public key object
-*/
-BOTAN_DLL Public_Key* copy_key(const Public_Key& key);
-
-/**
-* Create the key constraints for a specific public key.
-* @param pub_key the public key from which the basic set of
-* constraints to be placed in the return value is derived
-* @param limits additional limits that will be incorporated into the
-* return value
-* @return the combination of key type specific constraints and
-* additional limits
-*/
-
-BOTAN_DLL Key_Constraints find_constraints(const Public_Key& pub_key,
-                                           Key_Constraints limits);
-
-}
-
-}
-
-#endif
diff --git a/src/pubkey/pkcs8.cpp b/src/pubkey/pkcs8.cpp
new file mode 100644
index 000000000..099d52ffa
--- /dev/null
+++ b/src/pubkey/pkcs8.cpp
@@ -0,0 +1,309 @@
+/*
+* PKCS #8
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pkcs8.h>
+#include <botan/get_pbe.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/asn1_obj.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+#include <botan/internal/pk_algs.h>
+#include <memory>
+
+namespace Botan {
+
+namespace PKCS8 {
+
+namespace {
+
+/*
+* Get info from an EncryptedPrivateKeyInfo
+*/
+SecureVector<byte> PKCS8_extract(DataSource& source,
+                                 AlgorithmIdentifier& pbe_alg_id)
+   {
+   SecureVector<byte> key_data;
+
+   BER_Decoder(source)
+      .start_cons(SEQUENCE)
+         .decode(pbe_alg_id)
+         .decode(key_data, OCTET_STRING)
+      .verify_end();
+
+   return key_data;
+   }
+
+/*
+* PEM decode and/or decrypt a private key
+*/
+SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui,
+                                AlgorithmIdentifier& pk_alg_id)
+   {
+   AlgorithmIdentifier pbe_alg_id;
+   SecureVector<byte> key_data, key;
+   bool is_encrypted = true;
+
+   try {
+      if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
+         key_data = PKCS8_extract(source, pbe_alg_id);
+      else
+         {
+         std::string label;
+         key_data = PEM_Code::decode(source, label);
+         if(label == "PRIVATE KEY")
+            is_encrypted = false;
+         else if(label == "ENCRYPTED PRIVATE KEY")
+            {
+            DataSource_Memory key_source(key_data);
+            key_data = PKCS8_extract(key_source, pbe_alg_id);
+            }
+         else
+            throw PKCS8_Exception("Unknown PEM label " + label);
+         }
+
+      if(key_data.empty())
+         throw PKCS8_Exception("No key data found");
+      }
+   catch(Decoding_Error)
+      {
+      throw Decoding_Error("PKCS #8 private key decoding failed");
+      }
+
+   if(!is_encrypted)
+      key = key_data;
+
+   const u32bit MAX_TRIES = 3;
+
+   u32bit tries = 0;
+   while(true)
+      {
+      try {
+         if(MAX_TRIES && tries >= MAX_TRIES)
+            break;
+
+         if(is_encrypted)
+            {
+            DataSource_Memory params(pbe_alg_id.parameters);
+            std::auto_ptr<PBE> pbe(get_pbe(pbe_alg_id.oid, params));
+
+            User_Interface::UI_Result result = User_Interface::OK;
+            const std::string passphrase =
+               ui.get_passphrase("PKCS #8 private key", source.id(), result);
+
+            if(result == User_Interface::CANCEL_ACTION)
+               break;
+
+            pbe->set_key(passphrase);
+            Pipe decryptor(pbe.release());
+
+            decryptor.process_msg(key_data, key_data.size());
+            key = decryptor.read_all();
+            }
+
+         u32bit version;
+
+         BER_Decoder(key)
+            .start_cons(SEQUENCE)
+               .decode(version)
+               .decode(pk_alg_id)
+               .decode(key, OCTET_STRING)
+               .discard_remaining()
+            .end_cons();
+
+         if(version != 0)
+            throw Decoding_Error("PKCS #8: Unknown version number");
+
+         break;
+         }
+      catch(Decoding_Error)
+         {
+         ++tries;
+         }
+      }
+
+   if(key.empty())
+      throw Decoding_Error("PKCS #8 private key decoding failed");
+   return key;
+   }
+
+}
+
+/*
+* DER or PEM encode a PKCS #8 private key
+*/
+void encode(const Private_Key& key, Pipe& pipe, X509_Encoding encoding)
+   {
+   const u32bit PKCS8_VERSION = 0;
+
+   SecureVector<byte> contents =
+      DER_Encoder()
+         .start_cons(SEQUENCE)
+            .encode(PKCS8_VERSION)
+            .encode(key.algorithm_identifier())
+            .encode(key.pkcs8_private_key(), OCTET_STRING)
+         .end_cons()
+      .get_contents();
+
+   if(encoding == PEM)
+      pipe.write(PEM_Code::encode(contents, "PRIVATE KEY"));
+   else
+      pipe.write(contents);
+   }
+
+/*
+* Encode and encrypt a PKCS #8 private key
+*/
+void encrypt_key(const Private_Key& key,
+                 Pipe& pipe,
+                 RandomNumberGenerator& rng,
+                 const std::string& pass, const std::string& pbe_algo,
+                 X509_Encoding encoding)
+   {
+   const std::string DEFAULT_PBE = "PBE-PKCS5v20(SHA-1,AES-128/CBC)";
+
+   Pipe raw_key;
+   raw_key.start_msg();
+   encode(key, raw_key, RAW_BER);
+   raw_key.end_msg();
+
+   std::auto_ptr<PBE> pbe(get_pbe(((pbe_algo != "") ? pbe_algo : DEFAULT_PBE)));
+
+   pbe->new_params(rng);
+   pbe->set_key(pass);
+
+   AlgorithmIdentifier pbe_algid(pbe->get_oid(), pbe->encode_params());
+
+   Pipe key_encrytor(pbe.release());
+   key_encrytor.process_msg(raw_key);
+
+   SecureVector<byte> enc_key =
+      DER_Encoder()
+         .start_cons(SEQUENCE)
+            .encode(pbe_algid)
+            .encode(key_encrytor.read_all(), OCTET_STRING)
+         .end_cons()
+      .get_contents();
+
+   if(encoding == PEM)
+      pipe.write(PEM_Code::encode(enc_key, "ENCRYPTED PRIVATE KEY"));
+   else
+      pipe.write(enc_key);
+   }
+
+/*
+* PEM encode a PKCS #8 private key
+*/
+std::string PEM_encode(const Private_Key& key)
+   {
+   Pipe pem;
+   pem.start_msg();
+   encode(key, pem, PEM);
+   pem.end_msg();
+   return pem.read_all_as_string();
+   }
+
+/*
+* Encrypt and PEM encode a PKCS #8 private key
+*/
+std::string PEM_encode(const Private_Key& key,
+                       RandomNumberGenerator& rng,
+                       const std::string& pass,
+                       const std::string& pbe_algo)
+   {
+   if(pass == "")
+      return PEM_encode(key);
+
+   Pipe pem;
+   pem.start_msg();
+   encrypt_key(key, pem, rng, pass, pbe_algo, PEM);
+   pem.end_msg();
+   return pem.read_all_as_string();
+   }
+
+/*
+* Extract a private key and return it
+*/
+Private_Key* load_key(DataSource& source,
+                      RandomNumberGenerator& rng,
+                      const User_Interface& ui)
+   {
+   AlgorithmIdentifier alg_id;
+   SecureVector<byte> pkcs8_key = PKCS8_decode(source, ui, alg_id);
+
+   const std::string alg_name = OIDS::lookup(alg_id.oid);
+   if(alg_name == "" || alg_name == alg_id.oid.as_string())
+      throw PKCS8_Exception("Unknown algorithm OID: " +
+                            alg_id.oid.as_string());
+
+   std::auto_ptr<Private_Key> key(get_private_key(alg_name));
+
+   if(!key.get())
+      throw PKCS8_Exception("Unknown PK algorithm/OID: " + alg_name + ", " +
+                           alg_id.oid.as_string());
+
+   std::auto_ptr<PKCS8_Decoder> decoder(key->pkcs8_decoder(rng));
+
+   if(!decoder.get())
+      throw Decoding_Error("Key does not support PKCS #8 decoding");
+
+   decoder->alg_id(alg_id);
+   decoder->key_bits(pkcs8_key);
+
+   return key.release();
+   }
+
+/*
+* Extract a private key and return it
+*/
+Private_Key* load_key(const std::string& fsname,
+                      RandomNumberGenerator& rng,
+                      const User_Interface& ui)
+   {
+   DataSource_Stream source(fsname, true);
+   return PKCS8::load_key(source, rng, ui);
+   }
+
+/*
+* Extract a private key and return it
+*/
+Private_Key* load_key(DataSource& source,
+                      RandomNumberGenerator& rng,
+                      const std::string& pass)
+   {
+   return PKCS8::load_key(source, rng, User_Interface(pass));
+   }
+
+/*
+* Extract a private key and return it
+*/
+Private_Key* load_key(const std::string& fsname,
+                      RandomNumberGenerator& rng,
+                      const std::string& pass)
+   {
+   return PKCS8::load_key(fsname, rng, User_Interface(pass));
+   }
+
+/*
+* Make a copy of this private key
+*/
+Private_Key* copy_key(const Private_Key& key,
+                      RandomNumberGenerator& rng)
+   {
+   Pipe bits;
+
+   bits.start_msg();
+   PKCS8::encode(key, bits);
+   bits.end_msg();
+
+   DataSource_Memory source(bits.read_all());
+   return PKCS8::load_key(source, rng);
+   }
+
+}
+
+}
diff --git a/src/pubkey/pkcs8.h b/src/pubkey/pkcs8.h
new file mode 100644
index 000000000..9488c2c0b
--- /dev/null
+++ b/src/pubkey/pkcs8.h
@@ -0,0 +1,153 @@
+/*
+* PKCS #8
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PKCS8_H__
+#define BOTAN_PKCS8_H__
+
+#include <botan/x509_key.h>
+#include <botan/ui.h>
+
+namespace Botan {
+
+/*
+* PKCS #8 Private Key Decoder
+*/
+class BOTAN_DLL PKCS8_Decoder
+   {
+   public:
+      /**
+      * Set the algorithm identifier associated with the scheme
+      * this decoders key is part of.
+      * @param alg_id the algorithm identifier
+      */
+      virtual void alg_id(const AlgorithmIdentifier&) = 0;
+
+      /**
+      * Set the DER encoded key.
+      * @param key the DER encoded key
+      */
+      virtual void key_bits(const MemoryRegion<byte>&) = 0;
+      virtual ~PKCS8_Decoder() {}
+   };
+
+/**
+* PKCS #8 General Exception
+*/
+struct BOTAN_DLL PKCS8_Exception : public Decoding_Error
+   {
+   PKCS8_Exception(const std::string& error) :
+      Decoding_Error("PKCS #8: " + error) {}
+   };
+
+namespace PKCS8 {
+
+/**
+* Encode a private key into a pipe.
+* @param key the private key to encode
+* @param pipe the pipe to feed the encoded key into
+* @param enc the encoding type to use
+*/
+BOTAN_DLL void encode(const Private_Key& key, Pipe& pipe,
+                      X509_Encoding enc = PEM);
+
+/**
+* Encode and encrypt a private key into a pipe.
+* @param key the private key to encode
+* @param pipe the pipe to feed the encoded key into
+* @param pass the password to use for encryption
+* @param rng the rng to use
+* @param pbe_algo the name of the desired password-based encryption algorithm;
+         if empty ("") a reasonable (portable/secure) default will be chosen.
+* @param enc the encoding type to use
+*/
+BOTAN_DLL void encrypt_key(const Private_Key& key,
+                           Pipe& pipe,
+                           RandomNumberGenerator& rng,
+                           const std::string& pass,
+                           const std::string& pbe_algo = "",
+                           X509_Encoding enc = PEM);
+
+
+/**
+* Get a string containing a PEM encoded private key.
+* @param key the key to encode
+* @return the encoded key
+*/
+BOTAN_DLL std::string PEM_encode(const Private_Key& key);
+
+/**
+* Get a string containing a PEM encoded private key, encrypting it with a
+* password.
+* @param key the key to encode
+* @param rng the rng to use
+* @param pass the password to use for encryption
+* @param pbe_algo the name of the desired password-based encryption algorithm;
+         if empty ("") a reasonable (portable/secure) default will be chosen.
+*/
+BOTAN_DLL std::string PEM_encode(const Private_Key& key,
+                                 RandomNumberGenerator& rng,
+                                 const std::string& pass,
+                                 const std::string& pbe_algo = "");
+
+/**
+* Load a key from a data source.
+* @param source the data source providing the encoded key
+* @param rng the rng to use
+* @param ui the user interface to be used for passphrase dialog
+* @return the loaded private key object
+*/
+BOTAN_DLL Private_Key* load_key(DataSource& source,
+                                RandomNumberGenerator& rng,
+                                const User_Interface& ui);
+
+/** Load a key from a data source.
+* @param source the data source providing the encoded key
+* @param rng the rng to use
+* @param pass the passphrase to decrypt the key. Provide an empty
+* string if the key is not encoded.
+* @return the loaded private key object
+*/
+BOTAN_DLL Private_Key* load_key(DataSource& source,
+                                RandomNumberGenerator& rng,
+                                const std::string& pass = "");
+
+/**
+* Load a key from a file.
+* @param filename the path to the file containing the encoded key
+* @param rng the rng to use
+* @param ui the user interface to be used for passphrase dialog
+* @return the loaded private key object
+*/
+BOTAN_DLL Private_Key* load_key(const std::string& filename,
+                                RandomNumberGenerator& rng,
+                                const User_Interface& ui);
+
+/** Load a key from a file.
+* @param filename the path to the file containing the encoded key
+* @param rng the rng to use
+* @param pass the passphrase to decrypt the key. Provide an empty
+* string if the key is not encoded.
+* @return the loaded private key object
+*/
+BOTAN_DLL Private_Key* load_key(const std::string& filename,
+                                RandomNumberGenerator& rng,
+                                const std::string& pass = "");
+
+/**
+* Copy an existing encoded key object.
+* @param key the key to copy
+* @param rng the rng to use
+* @return the new copy of the key
+*/
+BOTAN_DLL Private_Key* copy_key(const Private_Key& key,
+                                RandomNumberGenerator& rng);
+
+}
+
+}
+
+#endif
diff --git a/src/pubkey/x509_key.cpp b/src/pubkey/x509_key.cpp
new file mode 100644
index 000000000..fdcfccf87
--- /dev/null
+++ b/src/pubkey/x509_key.cpp
@@ -0,0 +1,172 @@
+/*
+* X.509 Public Key
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/x509_key.h>
+#include <botan/filters.h>
+#include <botan/asn1_obj.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+#include <botan/internal/pk_algs.h>
+#include <memory>
+
+namespace Botan {
+
+namespace X509 {
+
+/*
+* DER or PEM encode a X.509 public key
+*/
+void encode(const Public_Key& key, Pipe& pipe, X509_Encoding encoding)
+   {
+   MemoryVector<byte> der =
+      DER_Encoder()
+         .start_cons(SEQUENCE)
+            .encode(key.algorithm_identifier())
+            .encode(key.x509_subject_public_key(), BIT_STRING)
+         .end_cons()
+      .get_contents();
+
+   if(encoding == PEM)
+      pipe.write(PEM_Code::encode(der, "PUBLIC KEY"));
+   else
+      pipe.write(der);
+   }
+
+/*
+* PEM encode a X.509 public key
+*/
+std::string PEM_encode(const Public_Key& key)
+   {
+   Pipe pem;
+   pem.start_msg();
+   encode(key, pem, PEM);
+   pem.end_msg();
+   return pem.read_all_as_string();
+   }
+
+/*
+* Extract a public key and return it
+*/
+Public_Key* load_key(DataSource& source)
+   {
+   try {
+      AlgorithmIdentifier alg_id;
+      MemoryVector<byte> key_bits;
+
+      if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
+         {
+         BER_Decoder(source)
+            .start_cons(SEQUENCE)
+            .decode(alg_id)
+            .decode(key_bits, BIT_STRING)
+            .verify_end()
+         .end_cons();
+         }
+      else
+         {
+         DataSource_Memory ber(
+            PEM_Code::decode_check_label(source, "PUBLIC KEY")
+            );
+
+         BER_Decoder(ber)
+            .start_cons(SEQUENCE)
+            .decode(alg_id)
+            .decode(key_bits, BIT_STRING)
+            .verify_end()
+         .end_cons();
+         }
+
+      if(key_bits.empty())
+         throw Decoding_Error("X.509 public key decoding failed");
+
+      const std::string alg_name = OIDS::lookup(alg_id.oid);
+      if(alg_name == "")
+         throw Decoding_Error("Unknown algorithm OID: " +
+                              alg_id.oid.as_string());
+
+      std::auto_ptr<Public_Key> key_obj(get_public_key(alg_name));
+      if(!key_obj.get())
+         throw Decoding_Error("Unknown PK algorithm/OID: " + alg_name + ", " +
+                              alg_id.oid.as_string());
+
+      std::auto_ptr<X509_Decoder> decoder(key_obj->x509_decoder());
+
+      if(!decoder.get())
+         throw Decoding_Error("Key does not support X.509 decoding");
+
+      decoder->alg_id(alg_id);
+      decoder->key_bits(key_bits);
+
+      return key_obj.release();
+      }
+   catch(Decoding_Error)
+      {
+      throw Decoding_Error("X.509 public key decoding failed");
+      }
+   }
+
+/*
+* Extract a public key and return it
+*/
+Public_Key* load_key(const std::string& fsname)
+   {
+   DataSource_Stream source(fsname, true);
+   return X509::load_key(source);
+   }
+
+/*
+* Extract a public key and return it
+*/
+Public_Key* load_key(const MemoryRegion<byte>& mem)
+   {
+   DataSource_Memory source(mem);
+   return X509::load_key(source);
+   }
+
+/*
+* Make a copy of this public key
+*/
+Public_Key* copy_key(const Public_Key& key)
+   {
+   Pipe bits;
+   bits.start_msg();
+   X509::encode(key, bits, RAW_BER);
+   bits.end_msg();
+   DataSource_Memory source(bits.read_all());
+   return X509::load_key(source);
+   }
+
+/*
+* Find the allowable key constraints
+*/
+Key_Constraints find_constraints(const Public_Key& pub_key,
+                                 Key_Constraints limits)
+   {
+   const Public_Key* key = &pub_key;
+   u32bit constraints = 0;
+
+   if(dynamic_cast<const PK_Encrypting_Key*>(key))
+      constraints |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT;
+
+   if(dynamic_cast<const PK_Key_Agreement_Key*>(key))
+      constraints |= KEY_AGREEMENT;
+
+   if(dynamic_cast<const PK_Verifying_wo_MR_Key*>(key) ||
+      dynamic_cast<const PK_Verifying_with_MR_Key*>(key))
+      constraints |= DIGITAL_SIGNATURE | NON_REPUDIATION;
+
+   if(limits)
+      constraints &= limits;
+
+   return Key_Constraints(constraints);
+   }
+
+}
+
+}
diff --git a/src/pubkey/x509_key.h b/src/pubkey/x509_key.h
new file mode 100644
index 000000000..a8f5267d7
--- /dev/null
+++ b/src/pubkey/x509_key.h
@@ -0,0 +1,99 @@
+/*
+* X.509 Public Key
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_PUBLIC_KEY_H__
+#define BOTAN_X509_PUBLIC_KEY_H__
+
+#include <botan/pipe.h>
+#include <botan/pk_keys.h>
+#include <botan/alg_id.h>
+#include <botan/pubkey_enums.h>
+
+namespace Botan {
+
+/**
+* This class represents abstract X.509 public key decoders.
+*/
+class BOTAN_DLL X509_Decoder
+   {
+   public:
+      virtual void alg_id(const AlgorithmIdentifier&) = 0;
+      virtual void key_bits(const MemoryRegion<byte>&) = 0;
+      virtual ~X509_Decoder() {}
+   };
+
+/**
+* This namespace contains functions for handling X509 objects.
+*/
+namespace X509 {
+
+/*
+* X.509 Public Key Encoding/Decoding
+*/
+
+/**
+* Encode a key into a pipe.
+* @param key the public key to encode
+* @param pipe the pipe to feed the encoded key into
+* @param enc the encoding type to use
+*/
+BOTAN_DLL void encode(const Public_Key& key, Pipe& pipe,
+                      X509_Encoding enc = PEM);
+
+/**
+* PEM encode a public key into a string.
+* @param key the key to encode
+* @return the PEM encoded key
+*/
+BOTAN_DLL std::string PEM_encode(const Public_Key& key);
+
+/**
+* Create a public key from a data source.
+* @param source the source providing the DER or PEM encoded key
+* @return the new public key object
+*/
+BOTAN_DLL Public_Key* load_key(DataSource& source);
+
+/**
+* Create a public key from a string.
+* @param enc the string containing the PEM encoded key
+* @return the new public key object
+*/
+BOTAN_DLL Public_Key* load_key(const std::string& enc);
+
+/**
+* Create a public key from a memory region.
+* @param enc the memory region containing the DER or PEM encoded key
+* @return the new public key object
+*/
+BOTAN_DLL Public_Key* load_key(const MemoryRegion<byte>& enc);
+
+/**
+* Copy a key.
+* @param key the public key to copy
+* @return the new public key object
+*/
+BOTAN_DLL Public_Key* copy_key(const Public_Key& key);
+
+/**
+* Create the key constraints for a specific public key.
+* @param pub_key the public key from which the basic set of
+* constraints to be placed in the return value is derived
+* @param limits additional limits that will be incorporated into the
+* return value
+* @return the combination of key type specific constraints and
+* additional limits
+*/
+
+BOTAN_DLL Key_Constraints find_constraints(const Public_Key& pub_key,
+                                           Key_Constraints limits);
+
+}
+
+}
+
+#endif
-- 
cgit v1.2.3