diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,6 +1,12 @@
 # Changelog for passman
 
-## Unreleased changes
+## 0.2
+
+- implemented manual saving
+- added a warning when changing master password
+- some code cleanup as suggested by [Stephen Paul Weber](https://github.com/singpolyma)
+
+## 0.1.1
 
 - corrected a bug that was causing the pwGenerate function to hang occasionally.
   - this may cause some passwords to be generated differently
diff --git a/app/UI.hs b/app/UI.hs
--- a/app/UI.hs
+++ b/app/UI.hs
@@ -63,6 +63,7 @@
     [ ( "add a password",         addPassword      )
     , ( "view/edit a password",   viewEditMenu     )
     , ( "change master password", changeMasterPass )
+    , ( "save manually",          save >> mainMenu )
     , ( "lock session",           lockSession      )
     , ( "quit",                   quit             )
     ]
@@ -93,9 +94,13 @@
 
 changeMasterPass :: S.StateT Status IO ()
 changeMasterPass = do
-  oldP <- S.gets $ view masterPass
-  newP <- req $ reqDefault getMasterPass oldP
-  S.modify $ set masterPass newP
+  req (confirm $
+    "\nWARNING: Changing your master password will change all of your saved passwords.\n" ++
+    "Are you sure you would like to proceed?") >>= flip when
+    (do
+      oldP <- S.gets $ view masterPass
+      newP <- req $ reqDefault getMasterPass oldP
+      S.modify $ set masterPass newP)
   mainMenu
 
 lockSession :: S.StateT Status IO ()
diff --git a/passman.cabal b/passman.cabal
--- a/passman.cabal
+++ b/passman.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 4a0cc4498747fbf939026e1fe1ad6b24fb5999132e9af2eb12c848da6ccf7cdf
+-- hash: c5c331a76842a12b6c072d80df3fe0d51970f056f11188205518ee6926790491
 
 name:           passman
-version:        0.1.1
+version:        0.2
 synopsis:       a simple password manager
 description:    Please see the README on GitHub at <https://github.com/jlamothe/passman#readme>
 category:       Security
@@ -38,6 +38,7 @@
       SHA
     , aeson
     , base >=4.7 && <5
+    , base16-bytestring
     , base64-bytestring
     , bytestring
     , containers
diff --git a/src/Password.hs b/src/Password.hs
--- a/src/Password.hs
+++ b/src/Password.hs
@@ -23,7 +23,7 @@
 -}
 
 {-# LANGUAGE TemplateHaskell #-}
-{-# LANGUAGE  OverloadedStrings #-}
+{-# LANGUAGE OverloadedStrings #-}
 
 module Password (
   -- * Data Types
@@ -59,6 +59,7 @@
   , (.=)
   )
 import qualified Data.ByteString.Lazy as B
+import qualified Data.ByteString.Base16.Lazy as B16
 import qualified Data.ByteString.Base64.Lazy as B64
 import Data.Char (isUpper, isLower, isDigit, isAlphaNum, toLower)
 import Data.Digest.Pure.SHA
@@ -322,12 +323,13 @@
 isSpecial = not . isAlphaNum
 
 mkPass :: String -> PWPolicy -> String
-mkPass (x:xs) p = let p' = nextPolicy x p in
-  if p^.pwLength <= 0
+mkPass [] _ = "" -- this should never happen
+mkPass (x:xs) p = if p^.pwLength <= 0
   then ""
-  else if validatePWPolicy p'
-  then x : mkPass xs p'
-  else mkPass xs p
+  else let p' = nextPolicy x p in
+    if validatePWPolicy p'
+    then x : mkPass xs p'
+    else mkPass xs p
 
 mkPool :: B.ByteString -> String
 mkPool = toB64 . raw where
@@ -338,10 +340,7 @@
 mkSeed pw d = toUTF8 pw `B.append` (d^.pwSalt)
 
 mkHash :: B.ByteString -> B.ByteString
-mkHash = raw . show . sha256 where
-  raw (x:y:xs) = read ("0x" ++ [x] ++ [y]) `B.cons` raw xs
-  raw [_] = error "odd number of hex digits in hash"
-  raw "" = B.empty
+mkHash = fst . B16.decode . encodeUtf8 . T.pack . show . sha256
 
 nextPolicy :: Char -> PWPolicy -> PWPolicy
 nextPolicy x p = over pwLength pred $
