diff --git a/Passbook.hs b/Passbook.hs
--- a/Passbook.hs
+++ b/Passbook.hs
@@ -3,28 +3,22 @@
 {-# OPTIONS_GHC -fno-warn-type-defaults #-}
 
 
-{- |This module provides different functions to sign a 'Pass' using Apple's @signpass@
-    command-line tool.
-
-    I intend to move the signing process to a Haskell native OpenSSL binding later
-    on, but due to time constraints didn't get around to it yet.
+{- |This module provides different functions to sign a Passbook 'Pass'.
 
-    If you want to use this module with an existing .pkpass file, you can import its
-    @pass.json@ file using the function 'loadPass'.
+    /Please read the documentation!/
 
-    The function 'signpass' creates a random UUID during the signing process, uses this UUID
-    as the passes' serial number and returns it along with the path to the signed pass.
+    One set of functions uses the @signpass@ tool included in Apple's Passbook
+    Support Materials to sign the pass. This uses the system keychain directly, but
+    works on OS X only.
 
-    The funciton 'signpassWithModifier' creates a random UUID during the signing process,
-    passes this UUID on to a function that modifies the pass accordingly (e.g. sets the serial
-    number or the barcode payload to the UUID) and otherwise works like 'signpass'.
-    The function 'updateBarcode' is provided as well.
+    The other set of functions uses OpenSSL instead, in this case you need to export
+    your certificate using the process described in the OpenSSL section of this document.
 
-    The function, 'signpassWithId', takes an existing ID and signs the pass
-    using that for the serial number and file name. This will most likely be used
-    for updating existing passes.
+    If you want to use this module with an existing .pkpass file, you can import it
+    using the function 'loadPass'. Please note that you still need to provide the
+    assets in a separate directory, 'loadPass' only parses the @pass.json@ file.
 
-    Using the function is very simple, assuming you have created a 'Pass' called
+    Using these function is very simple, assuming you have created a 'Pass' called
     @myPass@ and you have the related assets (e.g. the logo.png and icon.png files)
     stored in a folder named @myPass/@.
 
@@ -36,22 +30,25 @@
     You will find the pass at @path@ with the filename @passId.pkpass@. Using the
     types from "Passbook.Types" ensures that passes are generated correctly.
 
-    The @signpass@ utility must have access to your Keychain to be able to retrieve
-    your Pass Type Certificate for the pass to sign. You should run it once outside
-    of any program to grant it full access to your Keychain.
-
     Please note that an @icon.png@ file /must be/ present in your asset folder,
-    otherwise the generated pass will not work.
+    otherwise the generated pass will not work. This is /not/ checked by this module.
 
     Refer to Apple's Passbook documentation at <https://developer.apple.com/passbook/>
     for more information or to retrieve the @signpass@ tool which is included in the
     Passbook Support Materials. (iOS Developer Membership necessary)
 
-    This module will most likely only work on OS X machines.
 -}
-module Passbook ( signpass
+module Passbook ( -- * Sign using signpass
+                  -- $signpass
+                  signpass
                 , signpassWithId
                 , signpassWithModifier
+                  -- * Sign using OpenSSL
+                  -- $openssl
+                , signOpen
+                , signOpenWithModifier
+                , signOpenWithId
+                  -- * Helper functions
                 , genPassId
                 , updateBarcode
                 , loadPass
@@ -59,14 +56,17 @@
 
 import           Codec.Archive.Zip
 import           Control.Monad             (liftM)
+import           Control.Monad.IO.Class    (liftIO)
 import           Data.Aeson
-import           Data.ByteString.Lazy      as LB
+import qualified Data.ByteString.Lazy      as LB
 import           Data.Conduit
 import           Data.Conduit.Binary       hiding (sinkFile)
 import           Data.Conduit.Filesystem
 import qualified Data.Text                 as ST
-import           Data.Text.Lazy            as LT
+import           Data.Text.Lazy            (Text)
+import qualified Data.Text.Lazy            as LT
 import           Data.UUID
+import           Filesystem.Path           (filename)
 import           Filesystem.Path.CurrentOS (encodeString)
 import           Passbook.Types
 import           Prelude                   hiding (FilePath)
@@ -76,9 +76,22 @@
 
 default (LT.Text)
 
+-- $signpass
+--  These functions sign a 'Pass' using the @signpass@ tool provided by Apple in the
+--  Passbook Support Materials. You can find those at <https://developer.apple.com/passbook/>
+--  however, an iOS Developer Membership is necessary for the download.
+--
+--  The signpass utility needs access to your keychain. OS X will prompt you for this the first
+--  time you run the tool.
+--
+--  Please make sure that the @signpass@ tool is within your $PATH. These functions work on OS X
+--  only.
+
 -- |Takes the filepaths to the folder containing the path assets
 --  and the output folder, a 'Pass' and uses a random UUID to
 --  create and sign the pass.
+--
+--  /Important:/ OS X only!
 signpass :: FilePath -- ^ Input file path (asset directory)
          -> FilePath -- ^ Output file path
          -> Pass -- ^ The pass to sign
@@ -92,6 +105,10 @@
 --  modifier function that updates the pass with the generated UUID.
 --  This is useful for cases where you want to store the UUID in the barcode
 --  or some other field on the pass as well.
+--
+--  An example function for use with this is 'updateBarcode'.
+--
+--  /Important:/ OS X only!
 signpassWithModifier :: FilePath -- ^ Input file path (asset directory)
                      -> FilePath -- ^ Output file path
                      -> Pass -- ^ The pass to sign
@@ -103,13 +120,16 @@
     return (passPath, passId)
 
 -- |Updates the barcode in a pass with the UUID. This can be passed to 'signpassWithModifier'
+--  or 'signOpenWithModifier'.
 updateBarcode :: ST.Text -> Pass -> Pass
 updateBarcode n p = case barcode p of
     Nothing -> p -- This pass has no barcode.
     Just ob -> p { barcode = Just ob { altText = Just n
                                      , message = n } }
 
--- |Creates and signs a 'Pass' with an existing ID.
+-- |Signs the 'Pass' using the provided ID, no random UUID generation happens here.
+--
+--  /Important:/ OS X only!
 signpassWithId :: ST.Text -- ^ The pass ID
                -> FilePath -- ^ Input file path (asset directory)
                -> FilePath -- ^ Output file path
@@ -123,6 +143,102 @@
     signcmd lazyId tmp passOut
     rm_rf tmp
     return (passOut </> LT.append lazyId ".pkpass")
+
+-- |Helper function to generate a hash
+genHash :: FilePath -> Sh (Text, Text)
+genHash file = do
+    rawhash <- run "openssl" ["sha1", toTextIgnore file]
+    let hash = LT.drop 1 $ LT.dropWhile (/= ' ') rawhash
+    return (toTextIgnore $ filename file, LT.filter (/= '\n') hash)
+
+-- |Render JSON and put it in a file
+saveJSON :: ToJSON a => a -> FilePath -> IO ()
+saveJSON json path = LB.writeFile (LT.unpack $ toTextIgnore path) $ encode json
+
+-- |Helper function to sign the manifest
+sslSign :: FilePath -- ^ Certificate
+        -> FilePath -- ^ Key
+        -> FilePath -- ^ Temporary directory containing manifest.json
+        -> Sh Text
+sslSign cert key  tmp =
+    run "openssl" [ "smime", "-binary"
+                  , "-sign"
+                  , "-signer", toTextIgnore cert
+                  , "-inkey" , toTextIgnore key
+                  , "-in", "manifest.json"
+                  , "-out", "signature"
+                  , "-outform", "DER" ]
+
+-- $openssl
+--   These functions sign a 'Pass' using OpenSSL. They work on operating systems
+--   other than OS X as well. To use these you need to export your certificate
+--   from the keychain. Assuming you have saved the certificatea as @cert.p12@
+--   , the conversion works like this:
+--
+-- > $ openssl pkcs12 -in cert.p12 -clcerts -nokeys -out certificate.pem
+-- > $ openssl pkcs12 -in cert.p12 -nocerts -out keypw.pem
+--
+--   Enter a password for your key file, you will only need this once in the next step.
+--   Then strip the password from your key file using:
+--
+-- > $ openssl rsa -in keypw.pem -out key.pem
+--
+--   /Important:/ All paths passed to these functions /must/ be absolute.
+
+
+-- |Takes the filepaths to the folder containing the path assets
+--  and the output folder, the paths to the certificate and the key,
+--  a 'Pass' and uses a random UUID to create and sign the pass.
+signOpen :: FilePath -- ^ Input file path (asset directory)
+         -> FilePath -- ^ Output folder
+         -> FilePath -- ^ Certificate
+         -> FilePath -- ^ Certificate key
+         -> Pass     -- ^ The pass to sign
+         -> IO (FilePath, ST.Text) -- ^ The signed .pkpass file and ID
+signOpen passIn passOut cert key pass = do
+    passId <- genPassId
+    passPath <- signOpenWithId passIn passOut cert key pass passId
+    return (passPath, passId)
+
+-- |Works like 'signOpen', except for the fourth argument which is a
+--  modifier function that updates the pass with the generated UUID.
+--  This is useful for cases where you want to store the UUID in the barcode
+--  or some other field on the pass as well.
+--
+--  An example function for use with this is 'updateBarcode'.
+signOpenWithModifier :: FilePath -- ^ Input file path (asset directory)
+                     -> FilePath -- ^ Output folder
+                     -> FilePath -- ^ Certificate
+                     -> FilePath -- ^ Certificate key
+                     -> Pass     -- ^ The pass to sign
+                     -> (ST.Text -> Pass -> Pass) -- ^ Modifier function
+                     -> IO (FilePath, ST.Text) -- ^ The signed .pkpass file and ID
+signOpenWithModifier passIn passOut cert key pass f = do
+    passId <- genPassId
+    passPath <- signOpenWithId passIn passOut cert key (f passId pass) passId
+    return (passPath, passId)
+
+-- |Signs the 'Pass' using the provided ID, no random UUID generation happens here.
+signOpenWithId :: FilePath -- ^ Input file path (asset directory)
+               -> FilePath -- ^ Output folder
+               -> FilePath -- ^ Certificate
+               -> FilePath -- ^ Certificate key
+               -> Pass     -- ^ The pass to sign
+               -> ST.Text  -- ^ The pass ID
+               -> IO FilePath -- ^ The signed .pkpass file
+signOpenWithId passIn passOut cert key pass passId = shelly $ silently $ do
+    let tmp = passOut </> passId
+        passFile = LT.append (LT.fromStrict $ passId) ".pkpass"
+    cp_r passIn tmp
+    liftIO $ renderPass (tmp </> "pass.json") (pass { serialNumber = passId })
+    cd tmp
+    manifest <- liftM Manifest $ pwd >>= ls >>= mapM genHash
+    liftIO $ saveJSON manifest (tmp </> "manifest.json")
+    sslSign cert key tmp
+    files <- liftM (map (toTextIgnore . filename)) $ ls =<< pwd
+    run "zip" ((toTextIgnore $ passOut </> passFile) : files)
+    rm_rf tmp
+    return (passOut </> passFile)
 
 -- |Generates a random UUID for a Pass using "Data.UUID" and "System.Random"
 genPassId :: IO ST.Text
diff --git a/Passbook/Types.hs b/Passbook/Types.hs
--- a/Passbook/Types.hs
+++ b/Passbook/Types.hs
@@ -32,6 +32,7 @@
     , NumberStyle(..)
     , TransitType(..)
     , WebService(..)
+    , Manifest(..)
     -- * Auxiliary functions
     , rgb
     , mkBarcode
@@ -47,6 +48,7 @@
 import           Data.Attoparsec.Text
 import qualified Data.HashMap.Strict    as HM
 import           Data.Text              (Text, pack, unpack)
+import qualified Data.Text.Lazy         as LT
 import           Data.Time
 import           Data.Typeable
 import           System.Locale
@@ -193,6 +195,14 @@
 
     , passContent                :: PassType -- ^ The kind of pass and the passes' fields (required)
 } deriving (Eq, Ord, Show, Read, Typeable)
+
+-- |The manifest.json file
+data Manifest = Manifest [(LT.Text, LT.Text)] -- ^ (Filename, Hash)
+
+instance ToJSON Manifest where
+    toJSON (Manifest files) =
+      let pairs = map (\(f, h) -> LT.toStrict f .= h) files
+      in object pairs
 
 -- * JSON instances
 
diff --git a/hs-pkpass.cabal b/hs-pkpass.cabal
--- a/hs-pkpass.cabal
+++ b/hs-pkpass.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                hs-pkpass
-version:             0.3
+version:             0.4
 synopsis:            A library for Passbook pass creation & signing
 description:         A Haskell library for type-safe creation of Passbook passes and signing through Apple's signpass tool.
 homepage:            https://github.com/tazjin/hs-pkpass
@@ -38,4 +38,5 @@
                        unordered-containers >= 0.2,
                        zip-archive >= 0.1.1.8,
                        system-filepath < 0.5,
-                       bytestring
+                       bytestring,
+                       transformers >= 0.3
