diff --git a/hokey.hs b/hokey.hs
--- a/hokey.hs
+++ b/hokey.hs
@@ -22,12 +22,13 @@
 import Codec.Encryption.OpenPGP.Expirations (getKeyExpirationTimesFromSignature)
 import Codec.Encryption.OpenPGP.Fingerprint (fingerprint, eightOctetKeyID)
 import Codec.Encryption.OpenPGP.KeyInfo (pubkeySize, pkalgoAbbrev)
+import Codec.Encryption.OpenPGP.Serialize ()
 import Codec.Encryption.OpenPGP.Signatures (verifyTKWith, verifySigWith, verifyAgainstKeys)
 import Codec.Encryption.OpenPGP.Types
-import Control.Applicative ((<$>),(<*>))
+import Control.Applicative ((<$>),(<*>), pure)
 import Control.Arrow ((***), second)
 import Control.Error.Util (hush)
-import Control.Lens ((^.), (&), _1)
+import Control.Lens ((^.), (&), _1, _2, mapped, over)
 import Control.Monad.Trans.Resource (runResourceT)
 import Control.Monad.Trans.Writer.Lazy (execWriter, tell)
 import qualified Crypto.Hash.SHA3 as SHA3
@@ -38,15 +39,15 @@
 import qualified Data.ByteString.Base16 as Base16
 import Data.Conduit (($=),($$))
 import qualified Data.Conduit.Binary as CB
-import Data.Conduit.Cereal (conduitGet)
+import Data.Conduit.Cereal (conduitGet, conduitPut)
 import qualified Data.Conduit.List as CL
 import Data.Conduit.OpenPGP.Keyring (conduitToTKsDropping)
-import Data.List (unfoldr, elemIndex, findIndex, sortBy, intercalate)
+import Data.List (unfoldr, elemIndex, findIndex, sort, sortBy, intercalate)
 import qualified Data.Map as Map
 import Data.Maybe (fromMaybe, mapMaybe, listToMaybe)
 import Data.Monoid ((<>), mconcat, Monoid(..))
 import Data.Ord (comparing, Down(..))
-import Data.Serialize (get)
+import Data.Serialize (get, put)
 import Data.Time.Clock.POSIX (getPOSIXTime, posixSecondsToUTCTime, POSIXTime)
 import Data.Time.Format (formatTime)
 import qualified Data.Yaml as Y
@@ -56,7 +57,7 @@
 import Options.Applicative.Extra (customExecParser, helper)
 import Options.Applicative.Types (Parser)
 
-import System.IO (Handle, hFlush, hPutStrLn, stderr, stdin, hSetBuffering, BufferMode(..))
+import System.IO (Handle, hFlush, hPutStrLn, stderr, stdin, stdout, hSetBuffering, BufferMode(..))
 import System.Locale (defaultTimeLocale)
 
 import Text.PrettyPrint.ANSI.Leijen (colon, green, indent, linebreak, list, putDoc, red, text, yellow, (<+>), Doc) -- need 0.6.7 for hardline
@@ -229,7 +230,7 @@
     lintOutputFormat :: LintOutputFormat
 }
 
-data Command = CmdLint LintOptions
+data Command = CmdLint LintOptions | CmdCanonicalize
 
 lintO :: Parser LintOptions
 lintO = LintOptions
@@ -242,6 +243,7 @@
 
 dispatch :: Command -> IO ()
 dispatch (CmdLint o) = banner' stderr >> hFlush stderr >> doLint o
+dispatch (CmdCanonicalize) = banner' stderr >> hFlush stderr >> doCanonicalize
 
 main :: IO ()
 main = do
@@ -251,6 +253,7 @@
 cmd :: Parser Command
 cmd = subparser
     ( command "lint" (info ( CmdLint <$> lintO) ( progDesc "check key(s) for 'best practices'" ))
+   <> command "canonicalize" (info ( pure CmdCanonicalize) ( progDesc "arrange key components in a canonical ordering" ))
     )
 
 doLint :: LintOptions -> IO ()
@@ -262,6 +265,20 @@
         output Pretty cpt = mapM_ (putDoc . prettyKeyReport cpt)
         output JSON cpt = mapM_ (BL.putStr . flip BL.append (BL.singleton 0x0a) . jsonReport cpt)
         output YAML cpt = mapM_ (B.putStr . yamlReport cpt)
+
+doCanonicalize :: IO ()
+doCanonicalize = do
+    runResourceT $ CB.sourceHandle stdin $= conduitGet get $=
+                   conduitToTKsDropping $= CL.map canonicalize $=
+                   conduitPut put $$ CB.sinkHandle stdout
+    where
+        canonicalize (TK k r ui ua s) = TK k
+                                           (sort r)
+                                           (indepthsort ui)
+                                           (indepthsort ua)
+                                           (indepthsort s)
+        indepthsort :: (Ord a, Ord b) => [(a,[b])] -> [(a,[b])]
+        indepthsort = sort . over (mapped._2) sort
 
 banner' :: Handle -> IO ()
 banner' h = hPutStrLn h (banner "hokey" ++ "\n" ++ warranty "hokey")
diff --git a/hopenpgp-tools.cabal b/hopenpgp-tools.cabal
--- a/hopenpgp-tools.cabal
+++ b/hopenpgp-tools.cabal
@@ -1,5 +1,5 @@
 name:                hopenpgp-tools
-version:             0.8.2
+version:             0.9
 synopsis:            hOpenPGP-based command-line tools
 description:         command-line tools for performing some OpenPGP-related operations
 homepage:            http://floss.scru.org/hopenpgp-tools
@@ -51,7 +51,7 @@
                ,       cryptohash             >= 0.7.7
                ,       directory
                ,       errors
-               ,       hOpenPGP               >= 1.2
+               ,       hOpenPGP               >= 1.5.1
                ,       ixset
                ,       lens
                ,       old-locale
@@ -98,4 +98,4 @@
 source-repository this
   type:     git
   location: git://git.debian.org/users/clint/hopenpgp-tools.git
-  tag:      hopenpgp-tools/0.8.2
+  tag:      hopenpgp-tools/0.9
