diff options
Diffstat (limited to 'Data/OpenPGP/Util/DecryptSecretKey.hs')
-rw-r--r-- | Data/OpenPGP/Util/DecryptSecretKey.hs | 67 |
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) | |||
21 | import Data.Binary.Put (runPut) | 21 | import Data.Binary.Put (runPut) |
22 | import Control.Applicative ( (<$>) ) | 22 | import Control.Applicative ( (<$>) ) |
23 | 23 | ||
24 | import Crypto.Hash.SHA1 as SHA1 | ||
25 | |||
26 | import qualified Crypto.Cipher.AES as Vincent | 24 | import qualified Crypto.Cipher.AES as Vincent |
27 | import qualified Crypto.Cipher.Blowfish as Vincent | 25 | import qualified Crypto.Cipher.Blowfish as Vincent |
28 | 26 | ||
29 | import qualified Crypto.Cipher.Types as Vincent | 27 | import qualified Crypto.Cipher.Types as Vincent |
28 | |||
29 | #if defined(VERSION_cryptonite) | ||
30 | import qualified Data.ByteArray as Bytes | ||
31 | import Crypto.Hash.Algorithms | ||
32 | import Crypto.Hash | ||
33 | import Crypto.Error | ||
34 | #else | ||
30 | import qualified Data.Byteable as Vincent | 35 | import qualified Data.Byteable as Vincent |
36 | import Crypto.Hash.SHA1 as SHA1 | ||
37 | #endif | ||
31 | 38 | ||
32 | import qualified Crypto.Random as Vincent | 39 | import qualified Crypto.Random as Vincent |
33 | 40 | ||
34 | import Crypto.Cipher.Cast5 (CAST5_128) | 41 | import Crypto.Cipher.Cast5 (CAST5_128) |
35 | import Crypto.Cipher.ThomasToVincent | 42 | import Crypto.Cipher.ThomasToVincent |
36 | import Data.OpenPGP.Util.Base (toStrictBS,toLazyBS,hashBySymbol) | 43 | import Data.OpenPGP.Util.Base |
44 | import Data.OpenPGP.Util.Gen (makeGen) | ||
37 | 45 | ||
38 | 46 | data Enciphered = | |
39 | |||
40 | |||
41 | data 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 | ||
53 | withIV f (EncipheredZeroIV s) = f Vincent.nullIV s | 62 | withIV f (EncipheredZeroIV s) = f Vincent.nullIV s |
54 | 63 | ||
55 | decryptSecretKey :: | 64 | decryptSecretKey :: |
@@ -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 | |||
84 | decryptSecretKey _ _ = Nothing | 99 | decryptSecretKey _ _ = Nothing |
85 | 100 | ||
86 | checksum :: BS.ByteString -> Word16 | 101 | checksum :: BS.ByteString -> Word16 |
@@ -111,7 +126,8 @@ withS2K codec OpenPGP.AES128 s2k s = withIV $ codec (string2key s2k s :: Vince | |||
111 | withS2K codec OpenPGP.AES192 s2k s = withIV $ codec (string2key s2k s :: Vincent.AES192) | 126 | withS2K codec OpenPGP.AES192 s2k s = withIV $ codec (string2key s2k s :: Vincent.AES192) |
112 | withS2K codec OpenPGP.AES256 s2k s = withIV $ codec (string2key s2k s :: Vincent.AES256) | 127 | withS2K codec OpenPGP.AES256 s2k s = withIV $ codec (string2key s2k s :: Vincent.AES256) |
113 | withS2K codec OpenPGP.Blowfish s2k s = withIV $ codec (string2key s2k s :: Vincent.Blowfish128) | 128 | withS2K codec OpenPGP.Blowfish s2k s = withIV $ codec (string2key s2k s :: Vincent.Blowfish128) |
114 | withS2K 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) | ||
115 | withS2K codec algo _ _ = error $ "Unsupported symmetric algorithm : " ++ show algo ++ " in Data.OpenPGP.CryptoAPI.withS2K" | 131 | withS2K codec algo _ _ = error $ "Unsupported symmetric algorithm : " ++ show algo ++ " in Data.OpenPGP.CryptoAPI.withS2K" |
116 | 132 | ||
117 | withS2K' :: OpenPGP.SymmetricAlgorithm -> OpenPGP.S2K -> LZ.ByteString | 133 | withS2K' :: OpenPGP.SymmetricAlgorithm -> OpenPGP.S2K -> LZ.ByteString |
@@ -120,21 +136,27 @@ withS2K' OpenPGP.AES128 s2k s f = f (string2key s2k s :: Vincent.AES128) | |||
120 | withS2K' OpenPGP.AES192 s2k s f = f (string2key s2k s :: Vincent.AES192) | 136 | withS2K' OpenPGP.AES192 s2k s f = f (string2key s2k s :: Vincent.AES192) |
121 | withS2K' OpenPGP.AES256 s2k s f = f (string2key s2k s :: Vincent.AES256) | 137 | withS2K' OpenPGP.AES256 s2k s f = f (string2key s2k s :: Vincent.AES256) |
122 | withS2K' OpenPGP.Blowfish s2k s f = f (string2key s2k s :: Vincent.Blowfish128) | 138 | withS2K' OpenPGP.Blowfish s2k s f = f (string2key s2k s :: Vincent.Blowfish128) |
123 | withS2K' 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 |
126 | simpleUnCFB :: (Vincent.BlockCipher k) => k -> Vincent.IV k -> LZ.ByteString -> LZ.ByteString | 143 | simpleUnCFB :: (Vincent.BlockCipher k) => k -> Vincent.IV k -> LZ.ByteString -> LZ.ByteString |
127 | simpleUnCFB k iv = padThenUnpad k (toLazyBS . Vincent.cfbDecrypt k iv . toStrictBS) | 144 | simpleUnCFB k iv = padThenUnpad k (toLazyBS . Vincent.cfbDecrypt k iv . toStrictBS) |
128 | 145 | ||
129 | simpleCFB :: (Vincent.BlockCipher k, Vincent.CPRG g) => g -> k -> LZ.ByteString -> (LZ.ByteString, g) | 146 | simpleCFB :: (Vincent.BlockCipher k, RG g) => g -> k -> LZ.ByteString -> (LZ.ByteString, g) |
130 | simpleCFB g k bs = ( padThenUnpad k (LZ.fromChunks . (ivbs:) . (:[]) . Vincent.cfbEncrypt k iv . toStrictBS) bs | 147 | simpleCFB 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 | {- | ||
173 | Data/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 | -} | ||
150 | string2key :: (Vincent.BlockCipher k) => OpenPGP.S2K -> LZ.ByteString -> k | 183 | string2key :: (Vincent.BlockCipher k) => OpenPGP.S2K -> LZ.ByteString -> k |
151 | string2key s2k s = cipher | 184 | string2key 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) | |||
164 | encryptSecretKey :: BS.ByteString -> OpenPGP.S2K -> OpenPGP.SymmetricAlgorithm -> OpenPGP.Packet -> IO (Maybe OpenPGP.Packet) | 202 | encryptSecretKey :: BS.ByteString -> OpenPGP.S2K -> OpenPGP.SymmetricAlgorithm -> OpenPGP.Packet -> IO (Maybe OpenPGP.Packet) |
165 | encryptSecretKey passphrase s2k salgo plain = do | 203 | encryptSecretKey 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) ] |