packages feed

x509-util (empty) → 1.4.0

raw patch · 4 files changed

+372/−0 lines, 4 filesdep +asn1-encodingdep +asn1-typesdep +basesetup-changed

Dependencies added: asn1-encoding, asn1-types, base, bytestring, crypto-pubkey, crypto-pubkey-types, cryptohash, directory, pem, text, x509, x509-store, x509-system, x509-validation

Files

+ LICENSE view
@@ -0,0 +1,27 @@+Copyright (c) 2010-2013 Vincent Hanquez <vincent@snarc.org>++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.+2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.+3. Neither the name of the author nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Certificate.hs view
@@ -0,0 +1,306 @@+{-# LANGUAGE DeriveDataTypeable, OverloadedStrings #-}++import Data.Either+import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString.Lazy.Char8 as LC+import qualified Data.ByteString as B+import qualified Data.Text.Lazy as T+import Data.Text.Lazy.Encoding (decodeUtf8)+import Data.X509+import qualified Data.X509 as X509+import Data.List (find)+import Data.PEM (pemParseBS, pemContent, pemName)+import System.Console.GetOpt+import System.Environment+import Control.Monad+import Control.Applicative ((<$>))+import Data.Maybe+import System.Exit+import System.X509+import Data.X509.CertificateStore+import Data.X509.Validation++-- for signing/verifying certificate+import qualified Crypto.Hash.SHA1 as SHA1+import qualified Crypto.Hash.SHA224 as SHA224+import qualified Crypto.Hash.SHA256 as SHA256+import qualified Crypto.Hash.SHA512 as SHA512+import qualified Crypto.Hash.MD2 as MD2+import qualified Crypto.Hash.MD5 as MD5+import qualified Crypto.PubKey.HashDescr as HD+import qualified Crypto.PubKey.RSA as RSA+import qualified Crypto.Types.PubKey.RSA as RSA+import qualified Crypto.Types.PubKey.DSA as DSA+import qualified Crypto.PubKey.RSA.PKCS15 as RSA+import qualified Crypto.PubKey.DSA as DSA++import Data.ASN1.Encoding+import Data.ASN1.BinaryEncoding+import Data.ASN1.Types+import Data.ASN1.BitArray+import Text.Printf+import Numeric++hexdump :: B.ByteString -> String+hexdump bs = concatMap hex $ B.unpack bs+    where hex n+            | n > 0xa   = showHex n ""+            | otherwise = "0" ++ showHex n ""++hexdump' = hexdump++showDN (X509.DistinguishedName dn) = mapM_ toStr dn+  where toStr (oid, cs@(ASN1CharacterString e t)) =+            putStrLn ("  " ++ key ++ ": " ++ value)+          where key = show oid+                value = case asn1CharacterToString cs of+                            Nothing -> show e ++ " " ++ show t ++ " (decoding to string failed)"+                            Just s  -> show s ++ " (encoding : " ++ show e ++ ")"++showExts es@(Extensions Nothing) = do+    return ()+showExts es@(Extensions (Just exts)) = do+    mapM_ showExt exts+    putStrLn "known extensions decoded: "+    showKnownExtension (X509.extensionGet es :: Maybe X509.ExtBasicConstraints)+    showKnownExtension (X509.extensionGet es :: Maybe X509.ExtKeyUsage)+    showKnownExtension (X509.extensionGet es :: Maybe X509.ExtSubjectKeyId)+    showKnownExtension (X509.extensionGet es :: Maybe X509.ExtSubjectAltName)+    showKnownExtension (X509.extensionGet es :: Maybe X509.ExtAuthorityKeyId)+    where+        showExt (ExtensionRaw oid critical asn1) = do+            putStrLn ("  OID:  " ++ show oid ++ " critical: " ++ show critical)+            putStrLn ("        " ++ show asn1)+        showKnownExtension Nothing  = return ()+        showKnownExtension (Just e) = putStrLn ("  " ++ show e)++showCert :: SignedCertificate -> IO ()+showCert signedCert = do+    putStrLn ("version: " ++ show (X509.certVersion cert))+    putStrLn ("serial:  " ++ show (X509.certSerial cert))+    putStrLn ("sigalg:  " ++ show (X509.certSignatureAlg cert))+    putStrLn "issuer:"+    showDN $ X509.certIssuerDN cert+    putStrLn "subject:"+    showDN $ X509.certSubjectDN cert+    putStrLn ("valid:  " ++ show (X509.certValidity cert))+    case X509.certPubKey cert of+        X509.PubKeyRSA pubkey -> do+            putStrLn "public key RSA:"+            printf "  len    : %d bits\n" (RSA.public_size pubkey * 8)+            printf "  modulus: %x\n" (RSA.public_n pubkey)+            printf "  e      : %x\n" (RSA.public_e pubkey)+        X509.PubKeyDSA pubkey -> do+            let params = DSA.public_params pubkey+            putStrLn "public key DSA:"+            printf "  pub    : %x\n" (DSA.public_y pubkey)+            printf "  p      : %d\n" (DSA.params_p params)+            printf "  q      : %x\n" (DSA.params_q params)+            printf "  g      : %x\n" (DSA.params_g params)+        X509.PubKeyUnknown oid ws -> do+            printf "public key unknown: %s\n" (show oid)+            printf "  raw bytes: %s\n" (show ws)+            --case decodeASN1 BER $ L.pack ws of+            --    Left err -> printf "  asn1 decoding failed: %s\n" (show err)+            --    Right l  -> printf "  asn1 decoding:\n" >> showASN1 4 l+        pk                        ->+            printf "public key: %s\n" (show pk)+    case X509.certExtensions cert of+        (Extensions Nothing)   -> return ()+        (Extensions (Just es)) -> putStrLn "extensions:" >> showExts (X509.certExtensions cert)+    putStrLn ("sigAlg: " ++ show sigalg)+    putStrLn ("sig:    " ++ show sigbits)+  where+    signed  = X509.getSigned signedCert+    sigalg  = X509.signedAlg signed+    sigbits = X509.signedSignature signed+    cert    = X509.signedObject signed+++showRSAKey :: (RSA.KeyPair) -> String+showRSAKey (RSA.KeyPair privkey) = unlines+    [ "len-modulus:      " ++ (show $ RSA.public_size pubkey)+    , "modulus:          " ++ (show $ RSA.public_n pubkey)+    , "public exponant:  " ++ (show $ RSA.public_e pubkey)+    , "private exponant: " ++ (show $ RSA.private_d privkey)+    , "p1:               " ++ (show $ RSA.private_p privkey)+    , "p2:               " ++ (show $ RSA.private_q privkey)+    , "exp1:             " ++ (show $ RSA.private_dP privkey)+    , "exp2:             " ++ (show $ RSA.private_dQ privkey)+    , "coefficient:      " ++ (show $ RSA.private_qinv privkey)+    ]+  where pubkey = RSA.private_pub privkey++showDSAKey :: DSA.KeyPair -> String+showDSAKey (DSA.KeyPair params pubnum privnum) = unlines+    [ "priv     " ++ (printf "%x" $ privnum)+    , "pub:     " ++ (printf "%x" $ pubnum)+    , "p:       " ++ (printf "%x" $ DSA.params_p params)+    , "q:       " ++ (printf "%x" $ DSA.params_q params)+    , "g:       " ++ (printf "%x" $ DSA.params_g params)+    ]++showASN1 :: Int -> [ASN1] -> IO ()+showASN1 at = prettyPrint at where+    indent n = putStr (replicate n ' ')++    prettyPrint n []                 = return ()+    prettyPrint n (x@(Start _) : xs) = indent n >> p x >> putStrLn "" >> prettyPrint (n+1) xs+    prettyPrint n (x@(End _) : xs)   = indent (n-1) >> p x >> putStrLn "" >> prettyPrint (n-1) xs+    prettyPrint n (x : xs)           = indent n >> p x >> putStrLn "" >> prettyPrint n xs++    p (Boolean b)            = putStr ("bool: " ++ show b)+    p (IntVal i)             = putStr ("int: " ++ showHex i "")+    p (BitString bits)       = putStr ("bitstring: " ++ (hexdump $ bitArrayGetData bits))+    p (OctetString bs)       = putStr ("octetstring: " ++ hexdump bs)+    p (Null)                 = putStr "null"+    p (OID is)               = putStr ("OID: " ++ show is)+    p (Real d)               = putStr "real"+    p (Enumerated _)         = putStr "enum"+    p (Start Sequence)       = putStr "sequence"+    p (End Sequence)         = putStr "end-sequence"+    p (Start Set)            = putStr "set"+    p (End Set)              = putStr "end-set"+    p (Start _)              = putStr "container"+    p (End _)                = putStr "end-container"+    p (ASN1String cs)        = putCS cs+    p (ASN1Time TimeUTC time tz)      = putStr ("utctime: " ++ show time)+    p (ASN1Time TimeGeneralized time tz) = putStr ("generalizedtime: " ++ show time)+    p (Other tc tn x)        = putStr ("other(" ++ show tc ++ "," ++ show tn ++ ")")++    putCS (ASN1CharacterString UTF8 t)         = putStr ("utf8string:" ++ show t)+    putCS (ASN1CharacterString Numeric bs)     = putStr "numericstring:"+    putCS (ASN1CharacterString Printable t)    = putStr ("printablestring: " ++ show t)+    putCS (ASN1CharacterString T61 bs)         = putStr "t61string:"+    putCS (ASN1CharacterString VideoTex bs)    = putStr "videotexstring:"+    putCS (ASN1CharacterString IA5 bs)         = putStr "ia5string:"+    putCS (ASN1CharacterString Graphic bs)     = putStr "graphicstring:"+    putCS (ASN1CharacterString Visible bs)     = putStr "visiblestring:"+    putCS (ASN1CharacterString General bs)     = putStr "generalstring:"+    putCS (ASN1CharacterString UTF32 t)        = putStr ("universalstring:" ++ show t)+    putCS (ASN1CharacterString Character bs)   = putStr "characterstring:"+    putCS (ASN1CharacterString BMP t)          = putStr ("bmpstring: " ++ show t)++{-+    when (verify opts) $ getSystemCertificateStore >>= flip verifyCert x509+  where+        verifyCert store x509@(X509.X509 cert _ _ sigalg sig) = do+            case findCertificate (X509.certIssuerDN cert) store of+                Nothing                        -> putStrLn "couldn't find signing certificate"+                Just (X509.X509 syscert _ _ _ _) -> do+                    verifyAlg (B.concat $ L.toChunks $ X509.getSigningData x509)+                              (B.pack sig)+                              sigalg+                              (X509.certPubKey syscert)+-}++data X509Opts =+      DumpedRaw+    | DumpedText+    | ShowHash+    | Validate+    | ValidationHost String+    deriving (Show,Eq)++readPEMFile file = do+    content <- B.readFile file+    return $ either error id $ pemParseBS content++readSignedObject file = do+    content <- B.readFile file+    return $ either error (map (X509.decodeSignedObject . pemContent)) $ pemParseBS content++doCertMain opts files = do+    objs <- readSignedObject (head files)+    forM_ objs $ \o ->+        case o of+            Left err     -> error ("decoding Certificate failed: " ++ show err)+            Right signed -> do+                showCert signed+                when (ShowHash `elem` opts) $ hashCert signed+    when (Validate `elem` opts) $ do+        let cc = CertificateChain (rights objs)+        store  <- getSystemCertificateStore+        failed <- validate validationChecks store cc+        if failed /= []+            then putStrLn ("validation failed: " ++ show failed)+            else putStrLn "validation success"+  where+        hashCert signedCert = do+            putStrLn ("subject(MD5) old: " ++ hexdump' (X509.hashDN_old subject))+            putStrLn ("issuer(MD5) old:  " ++ hexdump' (X509.hashDN_old issuer))+            putStrLn ("subject(SHA1):    " ++ hexdump' (X509.hashDN subject))+            putStrLn ("issuer(SHA1):     " ++ hexdump' (X509.hashDN issuer))+            where+                subject = X509.certSubjectDN cert+                issuer  = X509.certIssuerDN cert+                cert    = X509.signedObject $ X509.getSigned signedCert+        validationChecks = (defaultChecks "") { checkFQHN       = foldl accHost Nothing opts+                                              , checkExhaustive = True+                                              }+        accHost Nothing (ValidationHost h) = Just h+        accHost a       _                  = a++doCRLMain opts files = do+    readSignedObject (head files) >>= \objs -> forM_ objs $ \o ->+        case o of+            Left err     -> error ("decoding CRL failed: " ++ show err)+            Right signed -> do+                putStrLn $ show $ getCRL signed++doASN1Main files = do+    pem <- readPEMFile (head files)+    forM_ pem $ \p ->+        case decodeASN1' BER $ pemContent p of+            Left err   -> error ("decoding ASN1 failed: " ++ show err)+            Right asn1 -> showASN1 0 asn1+    +doKeyMain files = do+    pems <- readPEMFile (head files)+    forM_ pems $ \pem -> do+        let content = either (error . show) id $ decodeASN1' BER (pemContent pem)+        case pemName pem of+            "RSA PRIVATE KEY" ->+                case fromASN1 content of+                    Left err    -> error ("not a valid RSA key: " ++ err)+                    Right (k,_) -> putStrLn "RSA KEY" >> putStrLn (showRSAKey k)+            "DSA PRIVATE KEY" ->+                case fromASN1 content of+                    Left err    -> error ("not a valid DSA key: " ++ err)+                    Right (k,_) -> putStrLn "DSA KEY" >> putStrLn (showDSAKey k)+            _                 ->+                putStrLn ("unknown private key: " ++ show (pemName pem))++optionsCert =+    [ Option []     ["hash"] (NoArg ShowHash) "output certificate hash"+    , Option ['v']  ["validate"] (NoArg Validate) "validate certificate"+    , Option []     ["validation-host"] (ReqArg ValidationHost "host") "validation host use for validation"+    ]++certMain = getoptMain optionsCert $ \o n -> doCertMain o n+crlMain = getoptMain [] $ \o n -> doCRLMain o n+keyMain = getoptMain [] $ \o n -> doKeyMain n+asn1Main = getoptMain [] $ \o n -> doASN1Main n++getoptMain opts f as =+    case getOpt Permute opts as of+        (o,n,[])  -> f o n+        (_,_,err) -> error (show err)++usage = do+    putStrLn "usage: x509-util <cmd>"+    putStrLn "  key : process public key"+    putStrLn "  cert: process X509 certificate"+    putStrLn "  crl : process CRL certificate"+    putStrLn "  asn1: show file asn1"++main = do+    args <- getArgs+    case args of+        []        -> usage+        "x509":as -> certMain as+        "cert":as -> certMain as+        "key":as  -> keyMain as+        "crl":as  -> crlMain as+        "asn1":as -> asn1Main as+        _         -> usage
+ x509-util.cabal view
@@ -0,0 +1,37 @@+Name:                x509-util+Version:             1.4.0+Description:         utility to parse, show, validate, sign and produce X509 certificates and chain.+License:             BSD3+License-file:        LICENSE+Copyright:           Vincent Hanquez <vincent@snarc.org>+Author:              Vincent Hanquez <vincent@snarc.org>+Maintainer:          Vincent Hanquez <vincent@snarc.org>+Synopsis:            Utility for X509 certificate and chain+Build-Type:          Simple+Category:            Data+stability:           experimental+Homepage:            http://github.com/vincenthz/hs-certificate+Cabal-Version:       >=1.6++Executable           x509-util+  Main-Is:           Certificate.hs+  hs-source-dirs:    src+  Buildable:         True+  Build-depends:     base >= 3 && < 5+                   , bytestring+                   , text >= 0.11+                   , crypto-pubkey-types+                   , x509+                   , x509-store+                   , x509-system+                   , x509-validation+                   , asn1-types >= 0.2+                   , asn1-encoding+                   , pem+                   , cryptohash+                   , crypto-pubkey+                   , directory++source-repository head+  type:     git+  location: git://github.com/vincenthz/hs-certificate