summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2014-04-15 20:09:34 -0400
committerjoe <joe@jerkface.net>2014-04-15 20:09:34 -0400
commit7cfd556b8681d0675b1a7df127bbdbe4b7c7e9ff (patch)
tree1df6f180509b595d31b4ceb23d40e568454f67bd
parentadab31d826113207bca7f4f7f9fb8013cead0ce1 (diff)
importing of PEM files
-rw-r--r--KeyRing.hs113
-rw-r--r--kiki.hs37
2 files changed, 84 insertions, 66 deletions
diff --git a/KeyRing.hs b/KeyRing.hs
index ced1994..52e8f67 100644
--- a/KeyRing.hs
+++ b/KeyRing.hs
@@ -15,6 +15,7 @@ import Data.List
15import Data.OpenPGP 15import Data.OpenPGP
16import Data.Functor 16import Data.Functor
17import Data.Monoid 17import Data.Monoid
18import Data.Tuple ( swap )
18import Data.Bits ( (.|.) ) 19import Data.Bits ( (.|.) )
19import Control.Applicative ( liftA2, (<$>) ) 20import Control.Applicative ( liftA2, (<$>) )
20import System.Directory ( getHomeDirectory, doesFileExist ) 21import System.Directory ( getHomeDirectory, doesFileExist )
@@ -77,6 +78,9 @@ data FileType = KeyRingFile PassWordFile | PEMFile UsageTag | WalletFile
77 78
78data RefType = ConstRef | MutableRef (Maybe Initializer) 79data RefType = ConstRef | MutableRef (Maybe Initializer)
79 80
81initializer (MutableRef x) = x
82initializer _ = Nothing
83
80 84
81data KeyRingRuntime = KeyRingRuntime 85data KeyRingRuntime = KeyRingRuntime
82 { rtPubring :: FilePath 86 { rtPubring :: FilePath
@@ -96,6 +100,7 @@ data KeyRingData = KeyRingData
96 , homeSpec :: Maybe String 100 , homeSpec :: Maybe String
97 } 101 }
98 102
103resolveInputFile :: FilePath -> FilePath -> InputFile -> [FilePath]
99resolveInputFile secring pubring = resolve 104resolveInputFile secring pubring = resolve
100 where 105 where
101 resolve HomeSec = return secring 106 resolve HomeSec = return secring
@@ -472,6 +477,44 @@ data KeySpec =
472 | KeyUidMatch String 477 | KeyUidMatch String
473 deriving Show 478 deriving Show
474 479
480parseSpec :: String -> String -> (KeySpec,Maybe String)
481parseSpec grip spec = (topspec,subspec)
482 where
483 (topspec0,subspec0) = unprefix '/' spec
484 (toptyp,top) = unprefix ':' topspec0
485 (subtyp,sub) = unprefix ':' subspec0
486 topspec = case () of
487 _ | null top && or [ subtyp=="fp"
488 , null subtyp && is40digitHex sub
489 ]
490 -> KeyGrip sub
491 _ | null top && null grip -> KeyUidMatch sub
492 _ | null top -> KeyGrip grip
493 _ | toptyp=="fp" || (null toptyp && is40digitHex top)
494 -> {- trace "using top" $ -} KeyGrip top
495 _ | toptyp=="u" -> KeyUidMatch top
496 _ | otherwise -> KeyUidMatch top
497 subspec = case subtyp of
498 "t" -> Just sub
499 "fp" | top=="" -> Nothing
500 "" | top=="" && is40digitHex sub -> Nothing
501 "" -> listToMaybe sub >> Just sub
502
503 is40digitHex xs = ys == xs && length ys==40
504 where
505 ys = filter ishex xs
506 ishex c | '0' <= c && c <= '9' = True
507 | 'A' <= c && c <= 'F' = True
508 | 'a' <= c && c <= 'f' = True
509 ishex c = False
510
511 unprefix c spec = if null (snd p) then swap p else (fst p, tail (snd p))
512 where p = break (==c) spec
513
514
515filterMatches :: KeySpec -> [(KeyKey,KeyData)] -> [(KeyKey,KeyData)]
516filterMatches spec ks = filter (matchSpec spec) ks
517
475 518
476buildKeyDB :: FilePath -> FilePath -> Maybe String -> KeyRingData 519buildKeyDB :: FilePath -> FilePath -> Maybe String -> KeyRingData
477 -> IO (KikiCondition ((KeyDB,Maybe String,Maybe Packet),[(FilePath,KikiReportAction)])) 520 -> IO (KikiCondition ((KeyDB,Maybe String,Maybe Packet),[(FilePath,KikiReportAction)]))
@@ -494,31 +537,7 @@ buildKeyDB secring pubring grip0 keyring = do
494 537
495 readw wk n = fmap (n,) (readPacketsFromWallet wk n) 538 readw wk n = fmap (n,) (readPacketsFromWallet wk n)
496 539
497 ms <- mapM readp (files isring) 540 importWalletKey wk db' (top,fname,sub,tag) = do
498 let grip = grip0 `mplus` (fingerprint <$> fstkey)
499 where
500 fstkey = listToMaybe $ mapMaybe isSecringKey ms
501 where isSecringKey (fn,Message ps)
502 | fn==secring = listToMaybe ps
503 isSecringKey _ = Nothing
504 db_rings = foldl' (uncurry . merge) Map.empty ms
505 wk = listToMaybe $ do
506 fp <- maybeToList grip
507 elm <- Map.toList db_rings
508 guard $ matchSpec (KeyGrip fp) elm
509 return $ keyPacket (snd elm)
510
511 wms <- mapM (readw wk) (files iswallet)
512 let wallet_keys = do
513 maybeToList wk
514 (fname,xs) <- wms
515 (_,sub,(_,m)) <- xs
516 (tag,top) <- Map.toList m
517 return (top,fname,sub,tag)
518
519 doDecrypt = todo
520
521 importWalletKey db' (top,fname,sub,tag) = do
522 try db' $ \(db',report0) -> do 541 try db' $ \(db',report0) -> do
523 r <- doImportG doDecrypt 542 r <- doImportG doDecrypt
524 db' 543 db'
@@ -537,12 +556,48 @@ buildKeyDB secring pubring grip0 keyring = do
537 try r $ \(db'',report) -> do 556 try r $ \(db'',report) -> do
538 return $ KikiSuccess (db'', report0 ++ report) 557 return $ KikiSuccess (db'', report0 ++ report)
539 558
540 db <- foldM importWalletKey (KikiSuccess (db_rings,[])) wallet_keys 559 doDecrypt = todo
560
561 -- KeyRings (todo: KikiCondition reporting?)
562 (db_rings,wk,grip) <- do
563 ms <- mapM readp (files isring)
564 let grip = grip0 `mplus` (fingerprint <$> fstkey)
565 where
566 fstkey = listToMaybe $ mapMaybe isSecringKey ms
567 where isSecringKey (fn,Message ps)
568 | fn==secring = listToMaybe ps
569 isSecringKey _ = Nothing
570 db_rings = foldl' (uncurry . merge) Map.empty ms
571
572 wk = listToMaybe $ do
573 fp <- maybeToList grip
574 elm <- Map.toList db_rings
575 guard $ matchSpec (KeyGrip fp) elm
576 return $ keyPacket (snd elm)
577 return (db_rings,wk,grip)
578
579 -- Wallets
580 wms <- mapM (readw wk) (files iswallet)
581 let wallet_keys = do
582 maybeToList wk
583 (fname,xs) <- wms
584 (_,sub,(_,m)) <- xs
585 (tag,top) <- Map.toList m
586 return (top,fname,sub,tag)
587 db <- foldM (importWalletKey wk) (KikiSuccess (db_rings,[])) wallet_keys
541 try db $ \(db,reportWallets) -> do 588 try db $ \(db,reportWallets) -> do
542 589
543 -- todo: import PEMFiles 590 -- PEM files
544 let imports = todo 591 let pems = do
545 db <- foldM importPEMKey (KikiSuccess (db,[])) (map snd imports) 592 (n,(rtyp,ftyp)) <- Map.toList $ kFiles keyring
593 grip <- maybeToList grip
594 (topspec,subspec) <- fmap (parseSpec grip) $ getUsage ftyp
595 n <- resolveInputFile secring pubring n
596 let ms = map fst $ filterMatches topspec (Map.toList db)
597 cmd = initializer rtyp
598 return (n,subspec,ms,cmd)
599 imports <- filterM (\(n,_,_,_) -> doesFileExist n) pems
600 db <- foldM importPEMKey (KikiSuccess (db,[])) imports
546 try db $ \(db,reportPEMs) -> do 601 try db $ \(db,reportPEMs) -> do
547 602
548 return $ KikiSuccess ( (db, grip, wk), reportWallets ++ reportPEMs ) 603 return $ KikiSuccess ( (db, grip, wk), reportWallets ++ reportPEMs )
diff --git a/kiki.hs b/kiki.hs
index b23e304..e901625 100644
--- a/kiki.hs
+++ b/kiki.hs
@@ -91,9 +91,6 @@ secp256k1_id = 0x2b8104000a
91 91
92warn str = hPutStrLn stderr str 92warn str = hPutStrLn stderr str
93 93
94unprefix c spec = if null (snd p) then swap p else (fst p, tail (snd p))
95 where p = break (==c) spec
96
97 94
98{- 95{-
99RSAPrivateKey ::= SEQUENCE { 96RSAPrivateKey ::= SEQUENCE {
@@ -653,14 +650,6 @@ getPassphrase cmd =
653 650
654#define HOMEOPTION (def &= explicit &= name "homedir" &= typDir ) 651#define HOMEOPTION (def &= explicit &= name "homedir" &= typDir )
655 652
656is40digitHex xs = ys == xs && length ys==40
657 where
658 ys = filter ishex xs
659 ishex c | '0' <= c && c <= '9' = True
660 | 'A' <= c && c <= 'F' = True
661 | 'a' <= c && c <= 'f' = True
662 ishex c = False
663
664flattenKeys :: Bool -> KeyDB -> Message 653flattenKeys :: Bool -> KeyDB -> Message
665flattenKeys isPublic db = Message $ concatMap (map packet . flattenTop "" isPublic . snd) (prefilter . Map.assocs $ db) 654flattenKeys isPublic db = Message $ concatMap (map packet . flattenTop "" isPublic . snd) (prefilter . Map.assocs $ db)
666 where 655 where
@@ -864,29 +853,6 @@ show_wip keyspec wkgrip db = do
864 let nwb = maybe 0x80 CryptoCoins.secretByteFromName $ snd s 853 let nwb = maybe 0x80 CryptoCoins.secretByteFromName $ snd s
865 putStrLn $ walletImportFormat nwb k 854 putStrLn $ walletImportFormat nwb k
866 855
867parseSpec :: String -> String -> (KeySpec,Maybe String)
868parseSpec grip spec = (topspec,subspec)
869 where
870 (topspec0,subspec0) = unprefix '/' spec
871 (toptyp,top) = unprefix ':' topspec0
872 (subtyp,sub) = unprefix ':' subspec0
873 topspec = case () of
874 _ | null top && or [ subtyp=="fp"
875 , null subtyp && is40digitHex sub
876 ]
877 -> KeyGrip sub
878 _ | null top && null grip -> KeyUidMatch sub
879 _ | null top -> KeyGrip grip
880 _ | toptyp=="fp" || (null toptyp && is40digitHex top)
881 -> {- trace "using top" $ -} KeyGrip top
882 _ | toptyp=="u" -> KeyUidMatch top
883 _ | otherwise -> KeyUidMatch top
884 subspec = case subtyp of
885 "t" -> Just sub
886 "fp" | top=="" -> Nothing
887 "" | top=="" && is40digitHex sub -> Nothing
888 "" -> listToMaybe sub >> Just sub
889
890-- | systemEnv 856-- | systemEnv
891-- This is like System.Process.system except that it lets you set 857-- This is like System.Process.system except that it lets you set
892-- some environment variables. 858-- some environment variables.
@@ -1766,9 +1732,6 @@ isTopKey p@(SecretKeyPacket {}) | not (is_subkey p) = True
1766isTopKey p@(PublicKeyPacket {}) | not (is_subkey p) = True 1732isTopKey p@(PublicKeyPacket {}) | not (is_subkey p) = True
1767isTopKey _ = False 1733isTopKey _ = False
1768 1734
1769filterMatches :: KeySpec -> [(KeyKey,KeyData)] -> [(KeyKey,KeyData)]
1770filterMatches spec ks = filter (matchSpec spec) ks
1771
1772selectSecretKey :: (KeySpec,Maybe String) -> KeyDB -> Maybe Packet 1735selectSecretKey :: (KeySpec,Maybe String) -> KeyDB -> Maybe Packet
1773selectSecretKey (spec,mtag) db = selectKey0 False (spec,mtag) db 1736selectSecretKey (spec,mtag) db = selectKey0 False (spec,mtag) db
1774 1737