From 52973c2c26fc2d3c529f0a11329c9784f87b3c72 Mon Sep 17 00:00:00 2001 From: Joe Crayne Date: Sat, 16 May 2020 07:44:58 -0400 Subject: Encode v5 keys (draft-ietf-openpgp-rfc4880bis-09). --- Data/OpenPGP.hs | 56 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/Data/OpenPGP.hs b/Data/OpenPGP.hs index a151e7b..cc97cd6 100644 --- a/Data/OpenPGP.hs +++ b/Data/OpenPGP.hs @@ -465,7 +465,13 @@ encode_public_key_material k | key_algorithm k `elem` [ECDSA,Ed25519,ECC] = do MPI y <- maybeToList $ lookup 'y' (key k) let xy = flag*(4^l) + x*(2^l) + y [ oid, encode (MPI xy), eccstuff ] -encode_public_key_material k = map (encode . (key k !)) (public_key_fields $ key_algorithm k) +encode_public_key_material k | Just fs <- known_public_key_fields (key_algorithm k) = + map (encode . (key k !)) fs +encode_public_key_material k = + -- encoding of a v5 opaque public key + let MPI opaque = key k ! 'L' + in [runPut . putByteString . integerToBS $ opaque] + getEllipticCurvePublicKey :: Get [(Char,MPI)] getEllipticCurvePublicKey = do @@ -568,26 +574,43 @@ put_packet (OnePassSignaturePacket { version = version, put_packet (SecretKeyPacket { version = version, timestamp = timestamp, key_algorithm = algorithm, key = key, s2k_useage = s2k_useage, s2k = s2k, + aead_algorithm = aead_algorithm, symmetric_algorithm = symmetric_algorithm, encrypted_data = encrypted_data, is_subkey = is_subkey }) = - (B.concat $ p : - (if s2k_useage `elem` [254,255] then - [encode s2k_useage, encode symmetric_algorithm, encode s2k] - else - [encode symmetric_algorithm] - ) ++ - (if symmetric_algorithm /= Unencrypted then + flip (,) (if is_subkey then 7 else 5) $ B.concat $ concat + [ [p,s2kbyte] + , if version == 5 + then [ B.singleton (fromIntegral $ sum $ map B.length s2k_stuff) ] + else [] + , s2k_stuff + , if version == 5 + then [ encode (fromIntegral (sum $ map B.length key_stuff) :: Word32) ] + else [] + , key_stuff + , if symmetric_algorithm == Unencrypted + then [ encode (checksum $ B.concat s) ] + else [] + ] + where + (s2kbyte,s2k_stuff) = case s2k_useage of + u | u `elem` [254,255] + -> (encode s2k_useage, [encode symmetric_algorithm, encode s2k]) + 253 | Just aead <- aead_algorithm + -> (encode s2k_useage, [encode symmetric_algorithm, encode aead, encode s2k]) + _ -> (encode symmetric_algorithm, []) + key_stuff = + if symmetric_algorithm /= Unencrypted then -- For V3 keys, the "encrypted data" has an unencrypted checksum -- of the unencrypted MPIs on the end [encrypted_data] - else s ++ - [encode $ checksum $ B.concat s]), - if is_subkey then 7 else 5) - where + else s p = fst (put_packet $ PublicKeyPacket version timestamp algorithm key False Nothing) - s = map (encode . (key !)) (secret_key_fields algorithm) + s = case known_secret_key_fields algorithm of + Nothing | Just (MPI opaque) <- lookup 'R' key + -> [ runPut (putByteString (integerToBS opaque)) ] + Just fs -> map (encode . (key !)) fs put_packet p@(PublicKeyPacket { version = v, timestamp = timestamp, key_algorithm = algorithm, key = key, is_subkey = is_subkey }) @@ -598,10 +621,15 @@ put_packet p@(PublicKeyPacket { version = v, timestamp = timestamp, encode v3_days, encode algorithm ] ++ material) - _ -> + 4 -> final (B.concat $ [ B.singleton 4, encode timestamp, encode algorithm ] ++ material) + 5 -> + final (B.concat $ [ + B.singleton 5, encode timestamp, encode algorithm, + encode (fromIntegral (sum $ map B.length material) :: Word32) + ] ++ material) where Just v3_days = v3_days_of_validity p final x = (x, if is_subkey then 14 else 6) -- cgit v1.2.3