diff options
author | Stephen Paul Weber <singpolyma@singpolyma.net> | 2011-08-02 19:07:18 -0500 |
---|---|---|
committer | Stephen Paul Weber <singpolyma@singpolyma.net> | 2011-08-02 19:07:18 -0500 |
commit | a7049687ad5a392cc16769a63ddfb221c13dfbf9 (patch) | |
tree | 00425740298874f4c038a936b8d838bccdd4ecd1 | |
parent | bde6687c6016bc81a95dbc033e475fce8a0e2594 (diff) |
SecretKeyPacket with parser
-rw-r--r-- | lib/OpenPGP.hs | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/lib/OpenPGP.hs b/lib/OpenPGP.hs index 373bd17..330c6a1 100644 --- a/lib/OpenPGP.hs +++ b/lib/OpenPGP.hs | |||
@@ -1,5 +1,6 @@ | |||
1 | module OpenPGP (Message(..), Packet(..), HashAlgorithm, KeyAlgorithm, CompressionAlgorithm, fingerprint) where | 1 | module OpenPGP (Message(..), Packet(..), HashAlgorithm, KeyAlgorithm, CompressionAlgorithm, fingerprint) where |
2 | 2 | ||
3 | import Control.Monad | ||
3 | import Data.Binary | 4 | import Data.Binary |
4 | import Data.Binary.Get | 5 | import Data.Binary.Get |
5 | import Data.Bits | 6 | import Data.Bits |
@@ -32,6 +33,20 @@ data Packet = | |||
32 | public_key_algorithm::KeyAlgorithm, | 33 | public_key_algorithm::KeyAlgorithm, |
33 | key::Map Char MPI | 34 | key::Map Char MPI |
34 | } | | 35 | } | |
36 | SecretKeyPacket { | ||
37 | version::Word8, | ||
38 | timestamp::Word32, | ||
39 | public_key_algorithm::KeyAlgorithm, | ||
40 | key::Map Char MPI, | ||
41 | s2k_useage::Word8, | ||
42 | symmetric_type::Word8, | ||
43 | s2k_type::Word8, | ||
44 | s2k_hash_algorithm::HashAlgorithm, | ||
45 | s2k_salt::Word64, | ||
46 | s2k_count::Word8, | ||
47 | encrypted_data::LZ.ByteString, | ||
48 | private_hash::LZ.ByteString | ||
49 | } | | ||
35 | CompressedDataPacket { | 50 | CompressedDataPacket { |
36 | compressed_data_algorithm::CompressionAlgorithm, | 51 | compressed_data_algorithm::CompressionAlgorithm, |
37 | message::Message | 52 | message::Message |
@@ -174,6 +189,14 @@ public_key_fields RSA_S = public_key_fields RSA | |||
174 | public_key_fields ELGAMAL = ['p', 'g', 'y'] | 189 | public_key_fields ELGAMAL = ['p', 'g', 'y'] |
175 | public_key_fields DSA = ['p', 'q', 'g', 'y'] | 190 | public_key_fields DSA = ['p', 'q', 'g', 'y'] |
176 | 191 | ||
192 | -- http://tools.ietf.org/html/rfc4880#section-5.5.3 | ||
193 | secret_key_fields :: KeyAlgorithm -> [Char] | ||
194 | secret_key_fields RSA = ['d', 'p', 'q', 'u'] | ||
195 | secret_key_fields RSA_E = public_key_fields RSA | ||
196 | secret_key_fields RSA_S = public_key_fields RSA | ||
197 | secret_key_fields ELGAMAL = ['x'] | ||
198 | secret_key_fields DSA = ['x'] | ||
199 | |||
177 | -- Helper method for fingerprints and such | 200 | -- Helper method for fingerprints and such |
178 | fingerprint_material :: Packet -> [LZ.ByteString] | 201 | fingerprint_material :: Packet -> [LZ.ByteString] |
179 | fingerprint_material (PublicKeyPacket {version = 4, | 202 | fingerprint_material (PublicKeyPacket {version = 4, |
@@ -218,6 +241,46 @@ parse_packet 4 = do | |||
218 | key_id = (BaseConvert.toString 16 key_id), | 241 | key_id = (BaseConvert.toString 16 key_id), |
219 | nested = nested | 242 | nested = nested |
220 | }) | 243 | }) |
244 | -- SecretKeyPacket, http://tools.ietf.org/html/rfc4880#section-5.5.3 | ||
245 | parse_packet 5 = do | ||
246 | -- Parse PublicKey part | ||
247 | (PublicKeyPacket { | ||
248 | version = version, | ||
249 | timestamp = timestamp, | ||
250 | public_key_algorithm = algorithm, | ||
251 | key = key | ||
252 | }) <- parse_packet 6 | ||
253 | s2k_useage <- get :: Get Word8 | ||
254 | let k = SecretKeyPacket version timestamp algorithm key s2k_useage | ||
255 | in do | ||
256 | k' <- case s2k_useage of | ||
257 | _ | s2k_useage == 255 || s2k_useage == 254 -> do | ||
258 | symmetric_type <- get | ||
259 | s2k_type <- get | ||
260 | s2k_hash_algorithm <- get | ||
261 | s2k_salt <- if s2k_type == 1 || s2k_type == 3 then get | ||
262 | else return undefined | ||
263 | s2k_count <- if s2k_type == 3 then do | ||
264 | c <- fmap fromIntegral (get :: Get Word8) | ||
265 | return $ fromIntegral $ | ||
266 | (16 + (c .&. 15)) `shiftL` ((c `shiftR` 4) + 6) | ||
267 | else return undefined | ||
268 | return (k symmetric_type s2k_type s2k_hash_algorithm | ||
269 | s2k_salt s2k_count) | ||
270 | _ | s2k_useage > 0 -> | ||
271 | -- s2k_useage is symmetric_type in this case | ||
272 | return (k s2k_useage undefined undefined undefined undefined) | ||
273 | _ -> | ||
274 | return (k undefined undefined undefined undefined undefined) | ||
275 | if s2k_useage > 0 then do | ||
276 | encrypted <- getRemainingLazyByteString | ||
277 | return (k' encrypted undefined) | ||
278 | else do | ||
279 | key <- foldM (\m f -> do | ||
280 | mpi <- get :: Get MPI | ||
281 | return $ Map.insert f mpi m) key (secret_key_fields algorithm) | ||
282 | private_hash <- getRemainingLazyByteString | ||
283 | return ((k' undefined private_hash) {key = key}) | ||
221 | -- PublicKeyPacket, http://tools.ietf.org/html/rfc4880#section-5.5.2 | 284 | -- PublicKeyPacket, http://tools.ietf.org/html/rfc4880#section-5.5.2 |
222 | parse_packet 6 = do | 285 | parse_packet 6 = do |
223 | version <- get :: Get Word8 | 286 | version <- get :: Get Word8 |