diff options
-rw-r--r-- | kiki.hs | 102 |
1 files changed, 47 insertions, 55 deletions
@@ -26,6 +26,7 @@ import System.Environment | |||
26 | import System.Exit | 26 | import System.Exit |
27 | import System.IO (hPutStrLn,stderr) | 27 | import System.IO (hPutStrLn,stderr) |
28 | import qualified Codec.Binary.Base64 as Base64 | 28 | import qualified Codec.Binary.Base64 as Base64 |
29 | import qualified Codec.Binary.Base16 as Base16 | ||
29 | import qualified Crypto.Hash.RIPEMD160 as RIPEMD160 | 30 | import qualified Crypto.Hash.RIPEMD160 as RIPEMD160 |
30 | import qualified Crypto.Hash.SHA256 as SHA256 | 31 | import qualified Crypto.Hash.SHA256 as SHA256 |
31 | import qualified Data.ByteString as S | 32 | import qualified Data.ByteString as S |
@@ -40,6 +41,7 @@ import Crypto.PubKey.RSA as RSA | |||
40 | import qualified Codec.Compression.GZip as GZip | 41 | import qualified Codec.Compression.GZip as GZip |
41 | import Data.Time.Clock.POSIX ( utcTimeToPOSIXSeconds ) | 42 | import Data.Time.Clock.POSIX ( utcTimeToPOSIXSeconds ) |
42 | import Data.Time.Clock ( UTCTime ) | 43 | import Data.Time.Clock ( UTCTime ) |
44 | import Data.Monoid ( (<>) ) | ||
43 | 45 | ||
44 | 46 | ||
45 | import DotLock | 47 | import DotLock |
@@ -353,25 +355,42 @@ parseCertBlob comp bs = do | |||
353 | (notBefore,notAfter) = certValidity cert | 355 | (notBefore,notAfter) = certValidity cert |
354 | case certPubKey cert of | 356 | case certPubKey cert of |
355 | PubKeyRSA key -> do | 357 | PubKeyRSA key -> do |
356 | let ex = let ekey = Char8.toStrict $ encodeASN1 DER (toASN1 key []) | 358 | let withoutkey = |
357 | (pre,post) = S.breakSubstring ekey $ Char8.toStrict bs | 359 | let ekey = Char8.toStrict $ encodeASN1 DER (toASN1 key []) |
358 | post' = S.drop (S.length ekey) post | 360 | (pre,post) = S.breakSubstring ekey $ Char8.toStrict bs |
359 | len :: Word16 | 361 | post' = S.drop (S.length ekey) post |
360 | len = if S.null post then maxBound | 362 | len :: Word16 |
361 | else fromIntegral $ S.length pre | 363 | len = if S.null post then maxBound |
362 | in encode len `L.append` GZip.compress (Char8.fromChunks [pre,post']) | 364 | else fromIntegral $ S.length pre |
365 | in if len < 4096 | ||
366 | then encode len `L.append` GZip.compress (Char8.fromChunks [pre,post']) | ||
367 | else bs | ||
363 | return | 368 | return |
364 | ParsedCert { pcertKey = packetFromPublicRSAKey notBefore | 369 | ParsedCert { pcertKey = packetFromPublicRSAKey notBefore |
365 | (MPI $ public_n key) | 370 | (MPI $ public_n key) |
366 | (MPI $ public_e key) | 371 | (MPI $ public_e key) |
367 | , pcertTimestamp = notBefore | 372 | , pcertTimestamp = notBefore |
368 | , pcertBlob = case comp of | 373 | , pcertBlob = if comp then withoutkey |
369 | 0 -> ex | 374 | else bs |
370 | 1 -> bs | ||
371 | 2 -> GZip.compress bs | ||
372 | } | 375 | } |
373 | _ -> Nothing | 376 | _ -> Nothing |
374 | 377 | ||
378 | decodeBlob cert = | ||
379 | if 0 /= (bs `L.index` 0) .&. 0x10 | ||
380 | then bs | ||
381 | else let (keypos0,bs') = L.splitAt 2 bs | ||
382 | keypos :: Word16 | ||
383 | keypos = decode keypos0 | ||
384 | ds = GZip.decompress bs' | ||
385 | (prekey,postkey) = L.splitAt (fromIntegral keypos) ds | ||
386 | in prekey <> key <> postkey | ||
387 | where | ||
388 | bs = pcertBlob cert | ||
389 | key = maybe L.empty (encodeASN1 DER . flip toASN1 []) $ rsaKeyFromPacket $ pcertKey cert | ||
390 | |||
391 | parsePEM :: L.ByteString -> L.ByteString -> (Message,L.ByteString) | ||
392 | parsePEM hdr bs = error "todo" | ||
393 | |||
375 | show_torhash pubkey _ = do | 394 | show_torhash pubkey _ = do |
376 | bs <- Char8.readFile pubkey | 395 | bs <- Char8.readFile pubkey |
377 | let parsekey f dta = do | 396 | let parsekey f dta = do |
@@ -391,50 +410,13 @@ show_cert certfile _ = do | |||
391 | bs <- Char8.readFile certfile | 410 | bs <- Char8.readFile certfile |
392 | let dta = extractPEM "CERTIFICATE" bs | 411 | let dta = extractPEM "CERTIFICATE" bs |
393 | mdta = L.pack <$> Base64.decode (Char8.unpack dta) | 412 | mdta = L.pack <$> Base64.decode (Char8.unpack dta) |
394 | {- | 413 | let c = mdta >>= parseCertBlob True |
395 | pubkey = RSA.PublicKey | 414 | d = mdta >>= parseCertBlob False |
396 | { public_size = 128 | 415 | -- e = mdta >>= parseCertBlob 2 |
397 | , public_n = 154361684503603802222425703762858923586891027963572326870083767113931020265732747123162809298697685461466566794668728252513238617267841367255306789892103614749619835666015844098056127878039846958283514957904585088494988419964303541700240003254472965884445634980070222782747273430139103311807958905274574715853 | ||
398 | , public_e = 65537} | ||
399 | pubkey2 = RSAKey8 | ||
400 | (MPI 154361684503603802222425703762858923586891027963572326870083767113931020265732747123162809298697685461466566794668728252513238617267841367255306789892103614749619835666015844098056127878039846958283514957904585088494988419964303541700240003254472965884445634980070222782747273430139103311807958905274574715853) | ||
401 | (MPI 65537) | ||
402 | mdta = Base64.decode (Char8.unpack dta) | ||
403 | cert = do | ||
404 | e <- decodeASN1 DER . L.pack <$> mdta | ||
405 | let scert = searchit bs -- decodeSignedCertificate $ Char8.toStrict (Char8.drop 4 bs) | ||
406 | scert :: Either String SignedCertificate | ||
407 | searchit bs | Char8.null bs = Left "thoroughly exhausted" | ||
408 | searchit bs = either (const $ searchit $ Char8.drop 1 bs) Right $ go bs | ||
409 | go bs | Char8.null bs = Left "exhausted" | ||
410 | go bs = either (const $ go $ Char8.init bs) Right $ (decodeSignedCertificate $ Char8.toStrict bs) | ||
411 | asn1 <- either (const Nothing) (Just) e | ||
412 | let asn1' = drop 2 asn1 -- getSequence 0 (drop 1 asn1) -- reverse $ dropWhile (/=End Sequence) $ drop 1 $ reverse asn1 | ||
413 | -- k <- either (Just . Left) (Just . Right . fst) (fromASN1 asn1') | ||
414 | k <- either (const Nothing) (Just . fst) (fromASN1 asn1') | ||
415 | let _ = k :: Certificate -- Either String Certificate | ||
416 | return (k,scert) -- (asn1', k) -- asn1 | ||
417 | ekey = encodeASN1 DER (toASN1 pubkey []) | ||
418 | ekey2 = encodeASN1 DER (toASN1 pubkey2 []) | ||
419 | ekey2_64 = Base64.encode $ L.unpack ekey2 | ||
420 | ex = do | ||
421 | dta <- mdta | ||
422 | let ekey_ = Char8.toStrict ekey | ||
423 | (pre,post) = S.breakSubstring ekey_ (S.pack dta) | ||
424 | post' = S.drop (S.length ekey_) post | ||
425 | return $ ( b64L $ GZip.compress (Char8.fromChunks [pre,post']), (b64 pre, b64 post')) | ||
426 | putStrLn $ show dta | ||
427 | putStrLn $ show (fmap fst cert) | ||
428 | -- putStrLn $ show (fmap snd cert) | ||
429 | putStrLn $ show (Base64.encode $ L.unpack ekey) | ||
430 | putStrLn $ show (Base64.encode $ L.unpack ekey2) | ||
431 | putStrLn $ show ex | ||
432 | -} | ||
433 | let c = mdta >>= parseCertBlob 0 | ||
434 | d = mdta >>= parseCertBlob 1 | ||
435 | e = mdta >>= parseCertBlob 2 | ||
436 | b64 = Base64.encode . S.unpack | 416 | b64 = Base64.encode . S.unpack |
437 | b64L = Base64.encode . L.unpack | 417 | b64L = Base64.encode . L.unpack |
418 | hex = Base16.encode . S.unpack | ||
419 | hexL = Base16.encode . L.unpack | ||
438 | putStrLn $ maybe "" (fingerprint . pcertKey) c | 420 | putStrLn $ maybe "" (fingerprint . pcertKey) c |
439 | putStrLn $ maybe "" (torhash . pcertKey) c | 421 | putStrLn $ maybe "" (torhash . pcertKey) c |
440 | putStrLn "" | 422 | putStrLn "" |
@@ -442,16 +424,26 @@ show_cert certfile _ = do | |||
442 | putStrLn $ maybe "" (("key = " ++) . show . pcertKey) c | 424 | putStrLn $ maybe "" (("key = " ++) . show . pcertKey) c |
443 | putStrLn "" | 425 | putStrLn "" |
444 | putStrLn $ maybe "" (("small blob length = " ++) . show . L.length . pcertBlob) c | 426 | putStrLn $ maybe "" (("small blob length = " ++) . show . L.length . pcertBlob) c |
445 | putStrLn "" | ||
446 | putStrLn $ maybe "" (("small blob = " ++) . b64L . pcertBlob) c | 427 | putStrLn $ maybe "" (("small blob = " ++) . b64L . pcertBlob) c |
428 | putStrLn $ maybe "" ((" decoded = " ++) . b64L . decodeBlob) c | ||
447 | putStrLn "" | 429 | putStrLn "" |
448 | putStrLn $ maybe "" ((" big blob length = " ++) . show . L.length . pcertBlob) d | 430 | putStrLn $ maybe "" ((" big blob length = " ++) . show . L.length . pcertBlob) d |
449 | putStrLn "" | ||
450 | putStrLn $ maybe "" ((" big blob = " ++) . b64L . pcertBlob) d | 431 | putStrLn $ maybe "" ((" big blob = " ++) . b64L . pcertBlob) d |
432 | putStrLn $ maybe "" ((" decoded = " ++) . b64L . decodeBlob) d | ||
433 | {- | ||
451 | putStrLn "" | 434 | putStrLn "" |
452 | putStrLn $ maybe "" ((" gzip blob length = " ++) . show . L.length . pcertBlob) e | 435 | putStrLn $ maybe "" ((" gzip blob length = " ++) . show . L.length . pcertBlob) e |
453 | putStrLn "" | 436 | putStrLn "" |
454 | putStrLn $ maybe "" ((" gzip blob = " ++) . b64L . pcertBlob) e | 437 | putStrLn $ maybe "" ((" gzip blob = " ++) . b64L . pcertBlob) e |
438 | -} | ||
439 | -- ASN1 starts: | ||
440 | -- 1 2 3 4 5 6 7 8 | ||
441 | -- cl....pc.tag.......... | ||
442 | -- Start Sequence tag = 0x10 | ||
443 | -- Start Sequence cl = 0 | ||
444 | let v = encodeASN1 DER [Start Sequence] | ||
445 | putStrLn "" | ||
446 | putStrLn $ "prefix = " ++ hexL v | ||
455 | return () | 447 | return () |
456 | 448 | ||
457 | cannonical_eckey x y = 0x4:pad32(numToBytes x) ++ pad32(numToBytes y) :: [Word8] | 449 | cannonical_eckey x y = 0x4:pad32(numToBytes x) ++ pad32(numToBytes y) :: [Word8] |