summaryrefslogtreecommitdiff
path: root/Data/OpenPGP/Util/DecryptSecretKey.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Data/OpenPGP/Util/DecryptSecretKey.hs')
-rw-r--r--Data/OpenPGP/Util/DecryptSecretKey.hs67
1 files changed, 52 insertions, 15 deletions
diff --git a/Data/OpenPGP/Util/DecryptSecretKey.hs b/Data/OpenPGP/Util/DecryptSecretKey.hs
index 9b63c8e..01728d3 100644
--- a/Data/OpenPGP/Util/DecryptSecretKey.hs
+++ b/Data/OpenPGP/Util/DecryptSecretKey.hs
@@ -21,24 +21,29 @@ import Control.Exception as Exception (IOException(..),catch)
21import Data.Binary.Put (runPut) 21import Data.Binary.Put (runPut)
22import Control.Applicative ( (<$>) ) 22import Control.Applicative ( (<$>) )
23 23
24import Crypto.Hash.SHA1 as SHA1
25
26import qualified Crypto.Cipher.AES as Vincent 24import qualified Crypto.Cipher.AES as Vincent
27import qualified Crypto.Cipher.Blowfish as Vincent 25import qualified Crypto.Cipher.Blowfish as Vincent
28 26
29import qualified Crypto.Cipher.Types as Vincent 27import qualified Crypto.Cipher.Types as Vincent
28
29#if defined(VERSION_cryptonite)
30import qualified Data.ByteArray as Bytes
31import Crypto.Hash.Algorithms
32import Crypto.Hash
33import Crypto.Error
34#else
30import qualified Data.Byteable as Vincent 35import qualified Data.Byteable as Vincent
36import Crypto.Hash.SHA1 as SHA1
37#endif
31 38
32import qualified Crypto.Random as Vincent 39import qualified Crypto.Random as Vincent
33 40
34import Crypto.Cipher.Cast5 (CAST5_128) 41import Crypto.Cipher.Cast5 (CAST5_128)
35import Crypto.Cipher.ThomasToVincent 42import Crypto.Cipher.ThomasToVincent
36import Data.OpenPGP.Util.Base (toStrictBS,toLazyBS,hashBySymbol) 43import Data.OpenPGP.Util.Base
44import Data.OpenPGP.Util.Gen (makeGen)
37 45
38 46data Enciphered =
39
40
41data Enciphered =
42 EncipheredWithIV !LZ.ByteString -- initial vector is appended to front of ByteString 47 EncipheredWithIV !LZ.ByteString -- initial vector is appended to front of ByteString
43 | EncipheredZeroIV !LZ.ByteString -- initial vector is zero, ByteString contains only the block 48 | EncipheredZeroIV !LZ.ByteString -- initial vector is zero, ByteString contains only the block
44 49
@@ -47,9 +52,13 @@ withIV f (EncipheredWithIV s) = f iv bs
47 where 52 where
48 Just iv = Vincent.makeIV (toStrictBS ivbs) 53 Just iv = Vincent.makeIV (toStrictBS ivbs)
49 (ivbs,bs) = LZ.splitAt (fromIntegral ivlen) s 54 (ivbs,bs) = LZ.splitAt (fromIntegral ivlen) s
55#if defined(VERSION_cryptonite)
56 ivlen = Bytes.length iv
57#else
50 ivlen = Vincent.byteableLength z 58 ivlen = Vincent.byteableLength z
51 z = Vincent.nullIV
52 _ = Vincent.constEqBytes z iv 59 _ = Vincent.constEqBytes z iv
60 z = Vincent.nullIV
61#endif
53withIV f (EncipheredZeroIV s) = f Vincent.nullIV s 62withIV f (EncipheredZeroIV s) = f Vincent.nullIV s
54 63
55decryptSecretKey :: 64decryptSecretKey ::
@@ -76,11 +85,17 @@ decryptSecretKey pass k@(OpenPGP.SecretKeyPacket {
76 (OpenPGP.secret_key_fields kalgo)) material 85 (OpenPGP.secret_key_fields kalgo)) material
77 (material, chk) = LZ.splitAt (LZ.length decd - chkSize) decd 86 (material, chk) = LZ.splitAt (LZ.length decd - chkSize) decd
78 (chkSize, chkF) 87 (chkSize, chkF)
79 | OpenPGP.s2k_useage k == 254 = (20, SHA1.hash . toStrictBS) 88 | OpenPGP.s2k_useage k == 254 = (20, sha1 . toStrictBS)
80 | otherwise = (2, toStrictBS . encode . checksum . toStrictBS) 89 | otherwise = (2, toStrictBS . encode . checksum . toStrictBS)
81 -- Words16s are written as 2 bytes in big-endian (network) order 90 -- Words16s are written as 2 bytes in big-endian (network) order
82 decd = withS2K simpleUnCFB salgo s2k (toLazyBS pass) (EncipheredWithIV encd) 91 decd = withS2K simpleUnCFB salgo s2k (toLazyBS pass) (EncipheredWithIV encd)
83 92
93#if defined(VERSION_cryptonite)
94 sha1 x = Bytes.convert (hash x :: Digest SHA1)
95#else
96 sha1 = SHA1.hash
97#endif
98
84decryptSecretKey _ _ = Nothing 99decryptSecretKey _ _ = Nothing
85 100
86checksum :: BS.ByteString -> Word16 101checksum :: BS.ByteString -> Word16
@@ -111,7 +126,8 @@ withS2K codec OpenPGP.AES128 s2k s = withIV $ codec (string2key s2k s :: Vince
111withS2K codec OpenPGP.AES192 s2k s = withIV $ codec (string2key s2k s :: Vincent.AES192) 126withS2K codec OpenPGP.AES192 s2k s = withIV $ codec (string2key s2k s :: Vincent.AES192)
112withS2K codec OpenPGP.AES256 s2k s = withIV $ codec (string2key s2k s :: Vincent.AES256) 127withS2K codec OpenPGP.AES256 s2k s = withIV $ codec (string2key s2k s :: Vincent.AES256)
113withS2K codec OpenPGP.Blowfish s2k s = withIV $ codec (string2key s2k s :: Vincent.Blowfish128) 128withS2K codec OpenPGP.Blowfish s2k s = withIV $ codec (string2key s2k s :: Vincent.Blowfish128)
114withS2K codec OpenPGP.CAST5 s2k s = withIV $ codec (string2key s2k s :: ThomasToVincent CAST5_128) 129-- TODO: cast5 support
130-- withS2K codec OpenPGP.CAST5 s2k s = withIV $ codec (string2key s2k s :: ThomasToVincent CAST5_128)
115withS2K codec algo _ _ = error $ "Unsupported symmetric algorithm : " ++ show algo ++ " in Data.OpenPGP.CryptoAPI.withS2K" 131withS2K codec algo _ _ = error $ "Unsupported symmetric algorithm : " ++ show algo ++ " in Data.OpenPGP.CryptoAPI.withS2K"
116 132
117withS2K' :: OpenPGP.SymmetricAlgorithm -> OpenPGP.S2K -> LZ.ByteString 133withS2K' :: OpenPGP.SymmetricAlgorithm -> OpenPGP.S2K -> LZ.ByteString
@@ -120,21 +136,27 @@ withS2K' OpenPGP.AES128 s2k s f = f (string2key s2k s :: Vincent.AES128)
120withS2K' OpenPGP.AES192 s2k s f = f (string2key s2k s :: Vincent.AES192) 136withS2K' OpenPGP.AES192 s2k s f = f (string2key s2k s :: Vincent.AES192)
121withS2K' OpenPGP.AES256 s2k s f = f (string2key s2k s :: Vincent.AES256) 137withS2K' OpenPGP.AES256 s2k s f = f (string2key s2k s :: Vincent.AES256)
122withS2K' OpenPGP.Blowfish s2k s f = f (string2key s2k s :: Vincent.Blowfish128) 138withS2K' OpenPGP.Blowfish s2k s f = f (string2key s2k s :: Vincent.Blowfish128)
123withS2K' OpenPGP.CAST5 s2k s f = f (string2key s2k s :: ThomasToVincent CAST5_128) 139-- TODO: cast5 support
140-- withS2K' OpenPGP.CAST5 s2k s f = f (string2key s2k s :: ThomasToVincent CAST5_128)
124 141
125-- decryption codec for withS2K 142-- decryption codec for withS2K
126simpleUnCFB :: (Vincent.BlockCipher k) => k -> Vincent.IV k -> LZ.ByteString -> LZ.ByteString 143simpleUnCFB :: (Vincent.BlockCipher k) => k -> Vincent.IV k -> LZ.ByteString -> LZ.ByteString
127simpleUnCFB k iv = padThenUnpad k (toLazyBS . Vincent.cfbDecrypt k iv . toStrictBS) 144simpleUnCFB k iv = padThenUnpad k (toLazyBS . Vincent.cfbDecrypt k iv . toStrictBS)
128 145
129simpleCFB :: (Vincent.BlockCipher k, Vincent.CPRG g) => g -> k -> LZ.ByteString -> (LZ.ByteString, g) 146simpleCFB :: (Vincent.BlockCipher k, RG g) => g -> k -> LZ.ByteString -> (LZ.ByteString, g)
130simpleCFB g k bs = ( padThenUnpad k (LZ.fromChunks . (ivbs:) . (:[]) . Vincent.cfbEncrypt k iv . toStrictBS) bs 147simpleCFB g k bs = ( padThenUnpad k (LZ.fromChunks . (ivbs:) . (:[]) . Vincent.cfbEncrypt k iv . toStrictBS) bs
131 , g' ) 148 , g' )
132 where 149 where
133 Just iv = Vincent.makeIV ivbs 150 Just iv = Vincent.makeIV ivbs
151#if defined(VERSION_cryptonite)
152 (ivbs,g') = Vincent.randomBytesGenerate ivlen g
153 ivlen = Bytes.length iv
154#else
155 z = Vincent.nullIV
134 (ivbs,g') = Vincent.cprgGenerate ivlen g 156 (ivbs,g') = Vincent.cprgGenerate ivlen g
135 ivlen = Vincent.byteableLength z 157 ivlen = Vincent.byteableLength z
136 z = Vincent.nullIV
137 _ = Vincent.constEqBytes z iv 158 _ = Vincent.constEqBytes z iv
159#endif
138 160
139-- Apply a function f to a zero-padded bytestring s to a multiple 161-- Apply a function f to a zero-padded bytestring s to a multiple
140-- of the blocksize for cyper k. 162-- of the blocksize for cyper k.
@@ -147,12 +169,28 @@ padThenUnpad k f s = dropPadEnd (f padded)
147 padAmount = blksize - (LZ.length s `mod` blksize) 169 padAmount = blksize - (LZ.length s `mod` blksize)
148 blksize = fromIntegral $ Vincent.blockSize k 170 blksize = fromIntegral $ Vincent.blockSize k
149 171
172{-
173Data/OpenPGP/Util/DecryptSecretKey.hs:172:20:
174 Couldn't match expected type ‘k’
175 with actual type ‘cryptonite-0.15:Crypto.Error.Types.CryptoFailable
176 cipher0’
177 ‘k’ is a rigid type variable bound by
178 the type signature for
179 string2key :: Vincent.BlockCipher k =>
180 OpenPGP.S2K -> LZ.ByteString -> k
181 at Data/OpenPGP/Util/DecryptSecretKey.hs:171:15
182-}
150string2key :: (Vincent.BlockCipher k) => OpenPGP.S2K -> LZ.ByteString -> k 183string2key :: (Vincent.BlockCipher k) => OpenPGP.S2K -> LZ.ByteString -> k
151string2key s2k s = cipher 184string2key s2k s = cipher
152 where 185 where
186#if defined(VERSION_cryptonite)
187 CryptoPassed cipher = Vincent.cipherInit k
188 k = toStrictBS $ LZ.take ksize $ OpenPGP.string2key hashBySymbol s2k s
189#else
153 cipher = Vincent.cipherInit k 190 cipher = Vincent.cipherInit k
154 Right k = Vincent.makeKey $ toStrictBS $ 191 Right k = Vincent.makeKey $ toStrictBS $
155 LZ.take ksize $ OpenPGP.string2key hashBySymbol s2k s 192 LZ.take ksize $ OpenPGP.string2key hashBySymbol s2k s
193#endif
156 ksize = case Vincent.cipherKeySize cipher of 194 ksize = case Vincent.cipherKeySize cipher of
157 Vincent.KeySizeFixed n -> fromIntegral n 195 Vincent.KeySizeFixed n -> fromIntegral n
158 Vincent.KeySizeEnum xs -> error $ "Unknown key size in string2key" 196 Vincent.KeySizeEnum xs -> error $ "Unknown key size in string2key"
@@ -164,8 +202,7 @@ catchIO_ a h = Exception.catch a (\(_ :: IOException) -> h)
164encryptSecretKey :: BS.ByteString -> OpenPGP.S2K -> OpenPGP.SymmetricAlgorithm -> OpenPGP.Packet -> IO (Maybe OpenPGP.Packet) 202encryptSecretKey :: BS.ByteString -> OpenPGP.S2K -> OpenPGP.SymmetricAlgorithm -> OpenPGP.Packet -> IO (Maybe OpenPGP.Packet)
165encryptSecretKey passphrase s2k salgo plain = do 203encryptSecretKey passphrase s2k salgo plain = do
166 flip catchIO_ (return Nothing) $ do 204 flip catchIO_ (return Nothing) $ do
167 g <- fmap Vincent.cprgCreate $ Vincent.createEntropyPool 205 g <- makeGen Nothing
168 let _ = g :: Vincent.SystemRNG
169 return $ Just 206 return $ Just
170 plain { OpenPGP.key = [ x | x <- OpenPGP.key plain 207 plain { OpenPGP.key = [ x | x <- OpenPGP.key plain
171 , fst x `elem` OpenPGP.public_key_fields (OpenPGP.key_algorithm plain) ] 208 , fst x `elem` OpenPGP.public_key_fields (OpenPGP.key_algorithm plain) ]