summaryrefslogtreecommitdiff
path: root/Data/OpenPGP/Util/Base.hs
blob: 5b3e159469e6958aae1c8cd9b79664e55b3a34b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
{-# LANGUAGE CPP #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE ConstraintKinds #-}
module Data.OpenPGP.Util.Base where

import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LZ
import Data.Binary (encode)
import Data.Word

import Data.OpenPGP as OpenPGP
#if defined(VERSION_cryptonite)
import Crypto.Hash
import Crypto.Hash.Algorithms as Vincent
import qualified Crypto.PubKey.ECC.Types as Vincent.ECDSA
import qualified Data.ByteArray as Bytes
import qualified Crypto.PubKey.ECC.ECDSA as Vincent.ECDSA
import Crypto.PubKey.RSA.PKCS15 (HashAlgorithmASN1)
#else
import Crypto.Hash.MD5 as MD5
import Crypto.Hash.SHA1 as SHA1
import Crypto.Hash.SHA256 as SHA256
import Crypto.Hash.SHA384 as SHA384
import Crypto.Hash.SHA512 as SHA512
import Crypto.Hash.SHA224 as SHA224
import Crypto.Hash.RIPEMD160 as RIPEMD160
import Crypto.PubKey.HashDescr as Vincent
import qualified Crypto.Types.PubKey.ECC as Vincent.ECDSA
import qualified Crypto.Types.PubKey.ECDSA as Vincent.ECDSA
#endif
import qualified Crypto.PubKey.RSA as Vincent.RSA
import qualified Crypto.Random as Vincent

import Data.OpenPGP.Util.Fingerprint (fingerprint)

#if defined(VERSION_cryptonite)
import Data.Hourglass
import System.Hourglass
import Control.Arrow (second)
import Data.Binary (decode)
#else
import qualified Data.Time.Clock.POSIX
#endif

hashBySymbol :: OpenPGP.HashAlgorithm -> LZ.ByteString -> BS.ByteString
#if defined(VERSION_cryptonite)
hashBySymbol OpenPGP.MD5 x = Bytes.convert (hashlazy x :: Digest MD5)
hashBySymbol OpenPGP.SHA1 x = Bytes.convert (hashlazy x :: Digest SHA1)
hashBySymbol OpenPGP.SHA256 x = Bytes.convert (hashlazy x :: Digest SHA256)
hashBySymbol OpenPGP.SHA384 x = Bytes.convert (hashlazy x :: Digest SHA384)
hashBySymbol OpenPGP.SHA512 x = Bytes.convert (hashlazy x :: Digest SHA512)
hashBySymbol OpenPGP.SHA224 x = Bytes.convert (hashlazy x :: Digest SHA224)
hashBySymbol OpenPGP.RIPEMD160 x = Bytes.convert (hashlazy x :: Digest RIPEMD160)
#else
hashBySymbol OpenPGP.MD5 = MD5.hashlazy
hashBySymbol OpenPGP.SHA1 = SHA1.hashlazy
hashBySymbol OpenPGP.SHA256 = SHA256.hashlazy
hashBySymbol OpenPGP.SHA384 = SHA384.hashlazy
hashBySymbol OpenPGP.SHA512 = SHA512.hashlazy
hashBySymbol OpenPGP.SHA224 = SHA224.hashlazy
hashBySymbol OpenPGP.RIPEMD160 = RIPEMD160.hashlazy
#endif

curveFromOID :: Integer -> Vincent.ECDSA.Curve
curveFromOID 0x2a8648ce3d030107 = Vincent.ECDSA.getCurveByName Vincent.ECDSA.SEC_p256r1 -- NIST P-256
curveFromOID 0x2B81040022       = Vincent.ECDSA.getCurveByName Vincent.ECDSA.SEC_p384r1 -- NIST P-384
curveFromOID 0x2B81040023       = Vincent.ECDSA.getCurveByName Vincent.ECDSA.SEC_p521r1 -- NIST P-521
curveFromOID 0x2b8104000a       = Vincent.ECDSA.getCurveByName Vincent.ECDSA.SEC_p256k1 -- bitcoin curve
curveFromOID n = error $ "Unknown curve: "++ show n

ecdsaKey k = Vincent.ECDSA.PublicKey curve (Vincent.ECDSA.Point x y)
 where
    x = keyParam 'x' k
    y = keyParam 'y' k
    curve = curveFromOID (keyParam 'c' k)


toStrictBS :: LZ.ByteString -> BS.ByteString
toStrictBS = BS.concat . LZ.toChunks

toLazyBS :: BS.ByteString -> LZ.ByteString
toLazyBS = LZ.fromChunks . (:[])

find_key :: OpenPGP.Message -> String -> Maybe OpenPGP.Packet
find_key = OpenPGP.find_key (show . fingerprint)



keyParam :: Char -> OpenPGP.Packet -> Integer
keyParam c k = fromJustMPI $ lookup c (OpenPGP.key k)
 where
    fromJustMPI :: Maybe OpenPGP.MPI -> Integer
    fromJustMPI (Just (OpenPGP.MPI x)) = x
    fromJustMPI _ =
        case k of
            PublicKeyPacket {} -> error $ "Missing "++show c++" field on "++show (key_algorithm k)++" packet."
            SecretKeyPacket {} -> error $ "Missing "++show c++" field on "++show (symmetric_algorithm k)
                                            ++" "++show (key_algorithm k)++" packet."

integerBytesize :: Integer -> Int
integerBytesize i = fromIntegral $ LZ.length (encode (OpenPGP.MPI i)) - 2

rsaKey :: OpenPGP.Packet -> Vincent.RSA.PublicKey
rsaKey k =
    Vincent.RSA.PublicKey (integerBytesize n) n (keyParam 'e' k)
    where
    n = keyParam 'n' k

-- http://tools.ietf.org/html/rfc3447#page-43
-- http://tools.ietf.org/html/rfc4880#section-5.2.2
#if defined(VERSION_cryptonite)
data HashDescr = forall hashAlg. HashAlgorithmASN1 hashAlg => HashDescr hashAlg

hashAlgoDesc OpenPGP.MD5       = HashDescr Vincent.MD5
hashAlgoDesc OpenPGP.SHA1      = HashDescr Vincent.SHA1
hashAlgoDesc OpenPGP.RIPEMD160 = HashDescr Vincent.RIPEMD160
hashAlgoDesc OpenPGP.SHA256    = HashDescr Vincent.SHA256
hashAlgoDesc OpenPGP.SHA384    = HashDescr Vincent.SHA384
hashAlgoDesc OpenPGP.SHA512    = HashDescr Vincent.SHA512
hashAlgoDesc OpenPGP.SHA224    = HashDescr Vincent.SHA224
#else
hashAlgoDesc OpenPGP.MD5       = Vincent.hashDescrMD5
hashAlgoDesc OpenPGP.SHA1      = Vincent.hashDescrSHA1
hashAlgoDesc OpenPGP.RIPEMD160 = Vincent.hashDescrRIPEMD160
hashAlgoDesc OpenPGP.SHA256    = Vincent.hashDescrSHA256
hashAlgoDesc OpenPGP.SHA384    = Vincent.hashDescrSHA384
hashAlgoDesc OpenPGP.SHA512    = Vincent.hashDescrSHA512
hashAlgoDesc OpenPGP.SHA224    = Vincent.hashDescrSHA224
#endif
hashAlgoDesc _ =
       error "Unsupported HashAlgorithm in hashAlgoDesc"


currentTime :: Integral b => IO b
#if defined(VERSION_hourglass)
currentTime = fromIntegral . toSeconds <$> dateCurrent
 where
    toSeconds vincentTime = t
      where (Elapsed (Seconds t)) = timeGetElapsed vincentTime
#else
currentTime = floor <$> Data.Time.Clock.POSIX.getPOSIXTime
#endif


#if defined(VERSION_cryptonite)
type RG = Vincent.DRG
#else
type RG = Vincent.CPRG
#endif