diff options
author | Stephen Paul Weber <singpolyma@singpolyma.net> | 2012-04-30 13:03:43 -0500 |
---|---|---|
committer | Stephen Paul Weber <singpolyma@singpolyma.net> | 2012-04-30 13:03:43 -0500 |
commit | eca03631b66b623c42677d4ca1af393c4322cb84 (patch) | |
tree | b513f043a3fb2b98b75fb555026c5fb1141a8f1b /Data | |
parent | be7580e37a1233be35131dcb957fe502cd47aa2f (diff) |
support subkeys
Diffstat (limited to 'Data')
-rw-r--r-- | Data/OpenPGP.hs | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/Data/OpenPGP.hs b/Data/OpenPGP.hs index 4904e54..d6da9de 100644 --- a/Data/OpenPGP.hs +++ b/Data/OpenPGP.hs | |||
@@ -171,7 +171,8 @@ data Packet = | |||
171 | version::Word8, | 171 | version::Word8, |
172 | timestamp::Word32, | 172 | timestamp::Word32, |
173 | key_algorithm::KeyAlgorithm, | 173 | key_algorithm::KeyAlgorithm, |
174 | key::[(Char,MPI)] | 174 | key::[(Char,MPI)], |
175 | is_subkey::Bool | ||
175 | } | | 176 | } | |
176 | SecretKeyPacket { | 177 | SecretKeyPacket { |
177 | version::Word8, | 178 | version::Word8, |
@@ -185,7 +186,8 @@ data Packet = | |||
185 | s2k_salt::Maybe Word64, | 186 | s2k_salt::Maybe Word64, |
186 | s2k_count::Maybe Word32, | 187 | s2k_count::Maybe Word32, |
187 | encrypted_data::B.ByteString, | 188 | encrypted_data::B.ByteString, |
188 | private_hash::Maybe B.ByteString -- the hash may be in the encrypted data | 189 | private_hash::Maybe B.ByteString, -- the hash may be in the encrypted data |
190 | is_subkey::Bool | ||
189 | } | | 191 | } | |
190 | CompressedDataPacket { | 192 | CompressedDataPacket { |
191 | compression_algorithm::CompressionAlgorithm, | 193 | compression_algorithm::CompressionAlgorithm, |
@@ -346,7 +348,8 @@ put_packet (SecretKeyPacket { version = version, timestamp = timestamp, | |||
346 | s2k_hash_algorithm = s2k_hash_algo, | 348 | s2k_hash_algorithm = s2k_hash_algo, |
347 | s2k_salt = s2k_salt, | 349 | s2k_salt = s2k_salt, |
348 | s2k_count = s2k_count, | 350 | s2k_count = s2k_count, |
349 | encrypted_data = encrypted_data }) = | 351 | encrypted_data = encrypted_data, |
352 | is_subkey = is_subkey }) = | ||
350 | (B.concat $ [p, encode s2k_useage] ++ | 353 | (B.concat $ [p, encode s2k_useage] ++ |
351 | (if s2k_useage `elem` [255, 254] then | 354 | (if s2k_useage `elem` [255, 254] then |
352 | [encode $ fromJust symmetric_type, encode s2k_t, | 355 | [encode $ fromJust symmetric_type, encode s2k_t, |
@@ -364,16 +367,20 @@ put_packet (SecretKeyPacket { version = version, timestamp = timestamp, | |||
364 | else | 367 | else |
365 | [encode (fromIntegral $ | 368 | [encode (fromIntegral $ |
366 | B.foldl (\c i -> (c + fromIntegral i) `mod` 65536) | 369 | B.foldl (\c i -> (c + fromIntegral i) `mod` 65536) |
367 | (0::Integer) (B.concat s) :: Word16)]), 5) | 370 | (0::Integer) (B.concat s) :: Word16)]), |
371 | if is_subkey then 7 else 5) | ||
368 | where | 372 | where |
369 | (Just s2k_t) = s2k_type | 373 | (Just s2k_t) = s2k_type |
370 | p = fst (put_packet $ PublicKeyPacket version timestamp algorithm key | 374 | p = fst (put_packet $ |
375 | PublicKeyPacket version timestamp algorithm key False | ||
371 | :: (B.ByteString, Integer)) -- Supress warning | 376 | :: (B.ByteString, Integer)) -- Supress warning |
372 | s = map (encode . (key !)) (secret_key_fields algorithm) | 377 | s = map (encode . (key !)) (secret_key_fields algorithm) |
373 | put_packet (PublicKeyPacket { version = 4, timestamp = timestamp, | 378 | put_packet (PublicKeyPacket { version = 4, timestamp = timestamp, |
374 | key_algorithm = algorithm, key = key }) = | 379 | key_algorithm = algorithm, key = key, |
380 | is_subkey = is_subkey }) = | ||
375 | (B.concat $ [B.singleton 4, encode timestamp, encode algorithm] ++ | 381 | (B.concat $ [B.singleton 4, encode timestamp, encode algorithm] ++ |
376 | map (encode . (key !)) (public_key_fields algorithm), 6) | 382 | map (encode . (key !)) (public_key_fields algorithm), |
383 | if is_subkey then 14 else 6) | ||
377 | put_packet (CompressedDataPacket { compression_algorithm = algorithm, | 384 | put_packet (CompressedDataPacket { compression_algorithm = algorithm, |
378 | message = message }) = | 385 | message = message }) = |
379 | (B.append (encode algorithm) $ compress algorithm $ encode message, 8) | 386 | (B.append (encode algorithm) $ compress algorithm $ encode message, 8) |
@@ -468,13 +475,13 @@ parse_packet 5 = do | |||
468 | return (k Nothing Nothing Nothing Nothing Nothing) | 475 | return (k Nothing Nothing Nothing Nothing Nothing) |
469 | if s2k_useage > 0 then do { | 476 | if s2k_useage > 0 then do { |
470 | encrypted <- getRemainingByteString; | 477 | encrypted <- getRemainingByteString; |
471 | return (k' encrypted Nothing) | 478 | return (k' encrypted Nothing False) |
472 | } else do | 479 | } else do |
473 | key <- foldM (\m f -> do | 480 | key <- foldM (\m f -> do |
474 | mpi <- get :: Get MPI | 481 | mpi <- get :: Get MPI |
475 | return $ (f,mpi):m) key (secret_key_fields algorithm) | 482 | return $ (f,mpi):m) key (secret_key_fields algorithm) |
476 | private_hash <- getRemainingByteString | 483 | private_hash <- getRemainingByteString |
477 | return ((k' B.empty (Just private_hash)) {key = key}) | 484 | return ((k' B.empty (Just private_hash) False) {key = key}) |
478 | -- PublicKeyPacket, http://tools.ietf.org/html/rfc4880#section-5.5.2 | 485 | -- PublicKeyPacket, http://tools.ietf.org/html/rfc4880#section-5.5.2 |
479 | parse_packet 6 = do | 486 | parse_packet 6 = do |
480 | version <- get :: Get Word8 | 487 | version <- get :: Get Word8 |
@@ -489,9 +496,14 @@ parse_packet 6 = do | |||
489 | version = 4, | 496 | version = 4, |
490 | timestamp = timestamp, | 497 | timestamp = timestamp, |
491 | key_algorithm = algorithm, | 498 | key_algorithm = algorithm, |
492 | key = key | 499 | key = key, |
500 | is_subkey = False | ||
493 | } | 501 | } |
494 | x -> fail $ "Unsupported PublicKeyPacket version " ++ show x ++ "." | 502 | x -> fail $ "Unsupported PublicKeyPacket version " ++ show x ++ "." |
503 | -- Secret-SubKey Packet, http://tools.ietf.org/html/rfc4880#section-5.5.1.4 | ||
504 | parse_packet 7 = do | ||
505 | p <- parse_packet 5 | ||
506 | return p {is_subkey = True} | ||
495 | -- CompressedDataPacket, http://tools.ietf.org/html/rfc4880#section-5.6 | 507 | -- CompressedDataPacket, http://tools.ietf.org/html/rfc4880#section-5.6 |
496 | parse_packet 8 = do | 508 | parse_packet 8 = do |
497 | algorithm <- get | 509 | algorithm <- get |
@@ -518,6 +530,10 @@ parse_packet 11 = do | |||
518 | -- UserIDPacket, http://tools.ietf.org/html/rfc4880#section-5.11 | 530 | -- UserIDPacket, http://tools.ietf.org/html/rfc4880#section-5.11 |
519 | parse_packet 13 = | 531 | parse_packet 13 = |
520 | fmap (UserIDPacket . B.toString) getRemainingByteString | 532 | fmap (UserIDPacket . B.toString) getRemainingByteString |
533 | -- Public-Subkey Packet, http://tools.ietf.org/html/rfc4880#section-5.5.1.2 | ||
534 | parse_packet 14 = do | ||
535 | p <- parse_packet 6 | ||
536 | return p {is_subkey = True} | ||
521 | -- ModificationDetectionCodePacket, http://tools.ietf.org/html/rfc4880#section-5.14 | 537 | -- ModificationDetectionCodePacket, http://tools.ietf.org/html/rfc4880#section-5.14 |
522 | parse_packet 19 = | 538 | parse_packet 19 = |
523 | fmap ModificationDetectionCodePacket getRemainingByteString | 539 | fmap ModificationDetectionCodePacket getRemainingByteString |
@@ -547,7 +563,7 @@ fingerprint_material (SecretKeyPacket {version = 4, | |||
547 | fingerprint_material PublicKeyPacket {version = 4, | 563 | fingerprint_material PublicKeyPacket {version = 4, |
548 | timestamp = timestamp, | 564 | timestamp = timestamp, |
549 | key_algorithm = algorithm, | 565 | key_algorithm = algorithm, |
550 | key = key} | 566 | key = key, is_subkey = False} |
551 | fingerprint_material p | version p `elem` [2, 3] = [n, e] | 567 | fingerprint_material p | version p `elem` [2, 3] = [n, e] |
552 | where | 568 | where |
553 | n = B.drop 2 (encode (key p ! 'n')) | 569 | n = B.drop 2 (encode (key p ! 'n')) |