summaryrefslogtreecommitdiff
path: root/Data/OpenPGP.hs
diff options
context:
space:
mode:
authorStephen Paul Weber <singpolyma@singpolyma.net>2012-04-25 11:11:09 -0500
committerStephen Paul Weber <singpolyma@singpolyma.net>2012-04-25 11:11:09 -0500
commitda82b6a356e6a1571047fdea15d26ec10c869fa4 (patch)
tree84876a89db1a41a81b36ab17b85b9e1dfeda15af /Data/OpenPGP.hs
parent7de451e7d9761126da49cc71ef1fe6eed728ccb4 (diff)
Make SignaturePacket opaque, emit trailer
Instead of the Put instance emitting the actual packet header, it emits the start of the trailer data (which is the same bytes as the packet header). SignaturePacket is opaque and there is a smart constructor, signaturePacket, that takes all the data *except* the trailer and auto-generates the trailer, making sure the trailer is always valid, so that the above becomes possible. WARNING: SignaturePacket is not *fully* opaque. You *may* still update fields directly using record syntax (on an already constructed packet). This may be useful, but if any of the values that make up the trailer are changed this will MAKE THE PACKET INVALID. This trade-off is deemed acceptable for now, but may change in the future. Any fields that do not affect the trailer (unhashed subpackets, etc) may be safely updated in this way. Other fields MUST be updated by constructing a new SignaturePacket with the smart constructor. This usage is exemplefied by Data.OpenPGP.Crypto The major upside of this is that it is now possible to re-emit unmodified (or even modified, if only fields not in the trailer are modified) SignaturePackets without invalidating the signature. Closes #11
Diffstat (limited to 'Data/OpenPGP.hs')
-rw-r--r--Data/OpenPGP.hs79
1 files changed, 65 insertions, 14 deletions
diff --git a/Data/OpenPGP.hs b/Data/OpenPGP.hs
index be50d1a..d950570 100644
--- a/Data/OpenPGP.hs
+++ b/Data/OpenPGP.hs
@@ -3,7 +3,47 @@
3-- The recommended way to import this module is: 3-- The recommended way to import this module is:
4-- 4--
5-- > import qualified Data.OpenPGP as OpenPGP 5-- > import qualified Data.OpenPGP as OpenPGP
6module Data.OpenPGP (Message(..), Packet(..), SignatureSubpacket(..), HashAlgorithm(..), KeyAlgorithm(..), CompressionAlgorithm(..), MPI(..), fingerprint_material, signatures_and_data, signature_issuer, calculate_signature_trailer, decode_s2k_count, encode_s2k_count) where 6module Data.OpenPGP (
7 Packet(OnePassSignaturePacket, PublicKeyPacket, SecretKeyPacket, CompressedDataPacket, LiteralDataPacket, UserIDPacket, UnsupportedPacket),
8 compression_algorithm,
9 content,
10 encrypted_data,
11 filename,
12 format,
13 hash_algorithm,
14 hashed_subpackets,
15 hash_head,
16 key,
17 key_algorithm,
18 key_id,
19 message,
20 nested,
21 private_hash,
22 s2k_count,
23 s2k_hash_algorithm,
24 s2k_salt,
25 s2k_type,
26 s2k_useage,
27 signature,
28 signature_type,
29 symmetric_type,
30 timestamp,
31 trailer,
32 unhashed_subpackets,
33 version,
34 isSignaturePacket,
35 signaturePacket,
36 Message(..),
37 SignatureSubpacket(..),
38 HashAlgorithm(..),
39 KeyAlgorithm(..),
40 CompressionAlgorithm(..),
41 MPI(..),
42 fingerprint_material,
43 signatures_and_data,
44 signature_issuer,
45 decode_s2k_count, encode_s2k_count
46) where
7 47
8import Control.Monad 48import Control.Monad
9import Data.Bits 49import Data.Bits
@@ -181,22 +221,16 @@ calculate_signature_trailer p =
181 221
182put_packet :: (Num a) => Packet -> (LZ.ByteString, a) 222put_packet :: (Num a) => Packet -> (LZ.ByteString, a)
183put_packet (SignaturePacket { version = 4, 223put_packet (SignaturePacket { version = 4,
184 signature_type = signature_type,
185 key_algorithm = key_algorithm,
186 hash_algorithm = hash_algorithm,
187 hashed_subpackets = hashed_subpackets,
188 unhashed_subpackets = unhashed_subpackets, 224 unhashed_subpackets = unhashed_subpackets,
189 hash_head = hash_head, 225 hash_head = hash_head,
190 signature = signature }) = 226 signature = signature,
191 (LZ.concat [ LZ.singleton 4, encode signature_type, 227 trailer = trailer }) =
192 encode key_algorithm, encode hash_algorithm, 228 (LZ.concat [ trailer_top,
193 encode (fromIntegral $ LZ.length hashed :: Word16),
194 hashed,
195 encode (fromIntegral $ LZ.length unhashed :: Word16), 229 encode (fromIntegral $ LZ.length unhashed :: Word16),
196 unhashed, 230 unhashed,
197 encode hash_head, encode signature ], 2) 231 encode hash_head, encode signature ], 2)
198 where 232 where
199 hashed = LZ.concat $ map encode hashed_subpackets 233 trailer_top = LZ.reverse $ LZ.drop 6 $ LZ.reverse trailer
200 unhashed = LZ.concat $ map encode unhashed_subpackets 234 unhashed = LZ.concat $ map encode unhashed_subpackets
201put_packet (OnePassSignaturePacket { version = version, 235put_packet (OnePassSignaturePacket { version = version,
202 signature_type = signature_type, 236 signature_type = signature_type,
@@ -522,10 +556,8 @@ signatures_and_data :: Message -> ([Packet], [Packet])
522signatures_and_data (Message ((CompressedDataPacket {message = m}):_)) = 556signatures_and_data (Message ((CompressedDataPacket {message = m}):_)) =
523 signatures_and_data m 557 signatures_and_data m
524signatures_and_data (Message lst) = 558signatures_and_data (Message lst) =
525 (filter isSig lst, filter isDta lst) 559 (filter isSignaturePacket lst, filter isDta lst)
526 where 560 where
527 isSig (SignaturePacket {}) = True
528 isSig _ = False
529 isDta (LiteralDataPacket {}) = True 561 isDta (LiteralDataPacket {}) = True
530 isDta _ = False 562 isDta _ = False
531 563
@@ -631,3 +663,22 @@ encode_s2k_count iterations
631 encode_s2k_count' count c 663 encode_s2k_count' count c
632 | count < 32 = (count, c) 664 | count < 32 = (count, c)
633 | otherwise = encode_s2k_count' (count `shiftR` 1) (c+1) 665 | otherwise = encode_s2k_count' (count `shiftR` 1) (c+1)
666
667-- SignaturePacket smart constructor
668signaturePacket :: Word8 -> Word8 -> KeyAlgorithm -> HashAlgorithm -> [SignatureSubpacket] -> [SignatureSubpacket] -> Word16 -> MPI -> Packet
669signaturePacket version signature_type key_algorithm hash_algorithm hashed_subpackets unhashed_subpackets hash_head signature =
670 let p = SignaturePacket {
671 version = version,
672 signature_type = signature_type,
673 key_algorithm = key_algorithm,
674 hash_algorithm = hash_algorithm,
675 hashed_subpackets = hashed_subpackets,
676 unhashed_subpackets = unhashed_subpackets,
677 hash_head = hash_head,
678 signature = signature,
679 trailer = undefined
680 } in p { trailer = calculate_signature_trailer p }
681
682isSignaturePacket :: Packet -> Bool
683isSignaturePacket (SignaturePacket {}) = True
684isSignaturePacket _ = False