summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2013-12-15 22:06:29 -0500
committerjoe <joe@jerkface.net>2013-12-15 22:06:29 -0500
commit395f75c6b7f66d313b4d44be4ed1317f9d7c7042 (patch)
treef66e931fb49cca89a0faa5bcc6a66c52418505a0
parent8dd042382eb2a676bac6cd266268ef4d3ed2b390 (diff)
Adapted to new ecc solutoin for OpenPGP-Haskell
-rw-r--r--Data/OpenPGP/Util/Base.hs16
-rw-r--r--Data/OpenPGP/Util/Sign.hs143
-rw-r--r--Data/OpenPGP/Util/Verify.hs23
-rw-r--r--openpgp-util.cabal1
4 files changed, 116 insertions, 67 deletions
diff --git a/Data/OpenPGP/Util/Base.hs b/Data/OpenPGP/Util/Base.hs
index 802d503..aaa02c7 100644
--- a/Data/OpenPGP/Util/Base.hs
+++ b/Data/OpenPGP/Util/Base.hs
@@ -14,6 +14,8 @@ import Crypto.Hash.SHA224 as SHA224
14import Crypto.Hash.RIPEMD160 as RIPEMD160 14import Crypto.Hash.RIPEMD160 as RIPEMD160
15import qualified Crypto.PubKey.RSA as Vincent.RSA 15import qualified Crypto.PubKey.RSA as Vincent.RSA
16import Crypto.PubKey.HashDescr as Vincent 16import Crypto.PubKey.HashDescr as Vincent
17import qualified Crypto.Types.PubKey.ECC as Vincent.ECDSA
18import qualified Crypto.Types.PubKey.ECDSA as Vincent.ECDSA
17 19
18import Data.OpenPGP.Util.Fingerprint (fingerprint) 20import Data.OpenPGP.Util.Fingerprint (fingerprint)
19 21
@@ -25,6 +27,20 @@ hashBySymbol OpenPGP.SHA512 = SHA512.hashlazy
25hashBySymbol OpenPGP.SHA224 = SHA224.hashlazy 27hashBySymbol OpenPGP.SHA224 = SHA224.hashlazy
26hashBySymbol OpenPGP.RIPEMD160 = RIPEMD160.hashlazy 28hashBySymbol OpenPGP.RIPEMD160 = RIPEMD160.hashlazy
27 29
30curveFromOID :: Integer -> Vincent.ECDSA.Curve
31curveFromOID 0x2a8648ce3d030107 = Vincent.ECDSA.getCurveByName Vincent.ECDSA.SEC_p256r1 -- NIST P-256
32curveFromOID 0x2B81040022 = Vincent.ECDSA.getCurveByName Vincent.ECDSA.SEC_p384r1 -- NIST P-384
33curveFromOID 0x2B81040023 = Vincent.ECDSA.getCurveByName Vincent.ECDSA.SEC_p521r1 -- NIST P-521
34curveFromOID 0x2b8104000a = Vincent.ECDSA.getCurveByName Vincent.ECDSA.SEC_p256k1 -- bitcoin curve
35curveFromOID n = error $ "Unknown curve: "++ show n
36
37ecdsaKey k = Vincent.ECDSA.PublicKey curve (Vincent.ECDSA.Point x y)
38 where
39 x = keyParam 'x' k
40 y = keyParam 'y' k
41 curve = curveFromOID (keyParam 'c' k)
42
43
28toStrictBS :: LZ.ByteString -> BS.ByteString 44toStrictBS :: LZ.ByteString -> BS.ByteString
29toStrictBS = BS.concat . LZ.toChunks 45toStrictBS = BS.concat . LZ.toChunks
30 46
diff --git a/Data/OpenPGP/Util/Sign.hs b/Data/OpenPGP/Util/Sign.hs
index e492f95..4a6eb4f 100644
--- a/Data/OpenPGP/Util/Sign.hs
+++ b/Data/OpenPGP/Util/Sign.hs
@@ -17,9 +17,15 @@ import qualified Crypto.Random as Vincent
17import qualified Crypto.PubKey.DSA as Vincent.DSA 17import qualified Crypto.PubKey.DSA as Vincent.DSA
18import qualified Crypto.PubKey.RSA as Vincent.RSA 18import qualified Crypto.PubKey.RSA as Vincent.RSA
19import qualified Crypto.PubKey.RSA.PKCS15 as Vincent.RSA 19import qualified Crypto.PubKey.RSA.PKCS15 as Vincent.RSA
20import qualified Crypto.PubKey.ECC.ECDSA as Vincent.ECDSA
20 21
21import Data.OpenPGP.Util.Base 22import Data.OpenPGP.Util.Base
22 23
24privateECDSAkey :: OpenPGP.Packet -> Vincent.ECDSA.PrivateKey
25privateECDSAkey k = Vincent.ECDSA.PrivateKey curve d
26 where
27 d = keyParam 'd' k
28 curve = curveFromOID (keyParam 'c' k)
23 29
24privateDSAkey :: OpenPGP.Packet -> Vincent.DSA.PrivateKey 30privateDSAkey :: OpenPGP.Packet -> Vincent.DSA.PrivateKey
25privateDSAkey k = Vincent.DSA.PrivateKey 31privateDSAkey k = Vincent.DSA.PrivateKey
@@ -46,74 +52,77 @@ privateRSAkey k =
46-- Operation is unsafe in that it silently re-uses "random" bytes when 52-- Operation is unsafe in that it silently re-uses "random" bytes when
47-- entropy runs out. Use pgpSign for a safer interface. 53-- entropy runs out. Use pgpSign for a safer interface.
48unsafeSign :: (Vincent.CPRG g) => -- CryptoRandomGen g) => 54unsafeSign :: (Vincent.CPRG g) => -- CryptoRandomGen g) =>
49 OpenPGP.Message -- ^ SecretKeys, one of which will be used 55 OpenPGP.Message -- ^ SecretKeys, one of which will be used
50 -> OpenPGP.SignatureOver -- ^ Data to sign, and optional signature packet 56 -> OpenPGP.SignatureOver -- ^ Data to sign, and optional signature packet
51 -> OpenPGP.HashAlgorithm -- ^ HashAlgorithm to use in signature 57 -> OpenPGP.HashAlgorithm -- ^ HashAlgorithm to use in signature
52 -> String -- ^ KeyID of key to choose 58 -> String -- ^ KeyID of key to choose
53 -> Integer -- ^ Timestamp for signature (unless sig supplied) 59 -> Integer -- ^ Timestamp for signature (unless sig supplied)
54 -> g -- ^ Random number generator 60 -> g -- ^ Random number generator
55 -> (OpenPGP.SignatureOver, g) 61 -> (OpenPGP.SignatureOver, g)
56unsafeSign keys over hsh keyid timestamp g = (over {OpenPGP.signatures_over = [sig]}, g') 62unsafeSign keys over hsh keyid timestamp g = (over {OpenPGP.signatures_over = [sig]}, g')
57 where 63 where
58 (final, g') = case OpenPGP.key_algorithm sig of 64 (final, g') = case OpenPGP.key_algorithm sig of
59 OpenPGP.DSA -> ([dsaR, dsaS], dsaG) 65 OpenPGP.DSA -> ([dsaR, dsaS], dsaG)
60 kalgo | kalgo `elem` [OpenPGP.RSA,OpenPGP.RSA_S] -> ([toNum rsaFinal], g) 66 OpenPGP.ECDSA -> ([ecdsaR,ecdsaS],ecdsaG)
61 | otherwise -> 67 kalgo | kalgo `elem` [OpenPGP.RSA,OpenPGP.RSA_S] -> ([toNum rsaFinal], g)
62 error ("Unsupported key algorithm " ++ show kalgo ++ "in sign") 68 | otherwise ->
63 (Vincent.DSA.Signature dsaR dsaS,dsaG) = let k' = privateDSAkey k in 69 error ("Unsupported key algorithm " ++ show kalgo ++ " in sign")
64 Vincent.DSA.sign g k' (dsaTruncate k' . bhash) dta 70 (Vincent.DSA.Signature dsaR dsaS,dsaG) = let k' = privateDSAkey k in
65 (Right rsaFinal,_) = Vincent.RSA.signSafer g desc (privateRSAkey k) dta 71 Vincent.DSA.sign g k' (dsaTruncate k' . bhash) dta
66 dsaTruncate (Vincent.DSA.PrivateKey (Vincent.DSA.Params _ _ q) _) = BS.take (integerBytesize q) 72 (Vincent.ECDSA.Signature ecdsaR ecdsaS,ecdsaG) = let k' = privateECDSAkey k in
67 dta = toStrictBS $ encode over `LZ.append` OpenPGP.trailer sig 73 Vincent.ECDSA.sign g k' bhash dta
68 sig = findSigOrDefault (listToMaybe $ OpenPGP.signatures_over over) 74 (Right rsaFinal,_) = Vincent.RSA.signSafer g desc (privateRSAkey k) dta
69 -- padding = emsa_pkcs1_v1_5_hash_padding hsh 75 dsaTruncate (Vincent.DSA.PrivateKey (Vincent.DSA.Params _ _ q) _) = BS.take (integerBytesize q)
70 desc = hashAlgoDesc hsh 76 dta = toStrictBS $ encode over `LZ.append` OpenPGP.trailer sig
71 bhash = hashBySymbol hsh . toLazyBS 77 sig = findSigOrDefault (listToMaybe $ OpenPGP.signatures_over over)
72 toNum = BS.foldl (\a b -> a `shiftL` 8 .|. fromIntegral b) 0 78 -- padding = emsa_pkcs1_v1_5_hash_padding hsh
73 Just k = find_key keys keyid 79 desc = hashAlgoDesc hsh
74 80 bhash = hashBySymbol hsh . toLazyBS
75 -- Either a SignaturePacket was found, or we need to make one 81 toNum = BS.foldl (\a b -> a `shiftL` 8 .|. fromIntegral b) 0
76 findSigOrDefault (Just s) = OpenPGP.signaturePacket 82 Just k = find_key keys keyid
77 (OpenPGP.version s) 83
78 (OpenPGP.signature_type s) 84 -- Either a SignaturePacket was found, or we need to make one
79 (OpenPGP.key_algorithm k) -- force to algo of key 85 findSigOrDefault (Just s) = OpenPGP.signaturePacket
80 hsh -- force hash algorithm 86 (OpenPGP.version s)
81 (OpenPGP.hashed_subpackets s) 87 (OpenPGP.signature_type s)
82 (OpenPGP.unhashed_subpackets s) 88 (OpenPGP.key_algorithm k) -- force to algo of key
83 (OpenPGP.hash_head s) 89 hsh -- force hash algorithm
84 (map OpenPGP.MPI final) 90 (OpenPGP.hashed_subpackets s)
85 findSigOrDefault Nothing = OpenPGP.signaturePacket 91 (OpenPGP.unhashed_subpackets s)
86 4 92 (OpenPGP.hash_head s)
87 defaultStype 93 (map OpenPGP.MPI final)
88 (OpenPGP.key_algorithm k) -- force to algo of key 94 findSigOrDefault Nothing = OpenPGP.signaturePacket
89 hsh 95 4
90 ([ 96 defaultStype
91 -- Do we really need to pass in timestamp just for the default? 97 (OpenPGP.key_algorithm k) -- force to algo of key
92 OpenPGP.SignatureCreationTimePacket $ fromIntegral timestamp, 98 hsh
93 OpenPGP.IssuerPacket $ fingerprint k 99 ([
94 ] ++ (case over of 100 -- Do we really need to pass in timestamp just for the default?
95 OpenPGP.KeySignature {} -> [OpenPGP.KeyFlagsPacket { 101 OpenPGP.SignatureCreationTimePacket $ fromIntegral timestamp,
96 OpenPGP.certify_keys = True, 102 OpenPGP.IssuerPacket $ fingerprint k
97 OpenPGP.sign_data = True, 103 ] ++ (case over of
98 OpenPGP.encrypt_communication = False, 104 OpenPGP.KeySignature {} -> [OpenPGP.KeyFlagsPacket {
99 OpenPGP.encrypt_storage = False, 105 OpenPGP.certify_keys = True,
100 OpenPGP.split_key = False, 106 OpenPGP.sign_data = True,
101 OpenPGP.authentication = False, 107 OpenPGP.encrypt_communication = False,
102 OpenPGP.group_key = False 108 OpenPGP.encrypt_storage = False,
103 }] 109 OpenPGP.split_key = False,
104 _ -> [] 110 OpenPGP.authentication = False,
105 )) 111 OpenPGP.group_key = False
106 [] 112 }]
107 0 -- TODO 113 _ -> []
108 (map OpenPGP.MPI final) 114 ))
109 115 []
110 defaultStype = case over of 116 0 -- TODO
111 OpenPGP.DataSignature ld _ 117 (map OpenPGP.MPI final)
112 | OpenPGP.format ld == 'b' -> 0x00 118
113 | otherwise -> 0x01 119 defaultStype = case over of
114 OpenPGP.KeySignature {} -> 0x1F 120 OpenPGP.DataSignature ld _
115 OpenPGP.SubkeySignature {} -> 0x18 121 | OpenPGP.format ld == 'b' -> 0x00
116 OpenPGP.CertificationSignature {} -> 0x13 122 | otherwise -> 0x01
123 OpenPGP.KeySignature {} -> 0x1F
124 OpenPGP.SubkeySignature {} -> 0x18
125 OpenPGP.CertificationSignature {} -> 0x13
117 126
118 127
119 128
diff --git a/Data/OpenPGP/Util/Verify.hs b/Data/OpenPGP/Util/Verify.hs
index 2367570..b42e664 100644
--- a/Data/OpenPGP/Util/Verify.hs
+++ b/Data/OpenPGP/Util/Verify.hs
@@ -1,5 +1,7 @@
1{-# LANGUAGE OverloadedStrings #-}
1module Data.OpenPGP.Util.Verify where 2module Data.OpenPGP.Util.Verify where
2 3
4import Debug.Trace
3import qualified Data.OpenPGP as OpenPGP 5import qualified Data.OpenPGP as OpenPGP
4import Data.Maybe 6import Data.Maybe
5import Data.Binary (encode) 7import Data.Binary (encode)
@@ -9,6 +11,8 @@ import qualified Data.ByteString.Lazy as LZ
9 11
10import qualified Crypto.PubKey.DSA as Vincent.DSA 12import qualified Crypto.PubKey.DSA as Vincent.DSA
11import qualified Crypto.PubKey.RSA.PKCS15 as Vincent.RSA 13import qualified Crypto.PubKey.RSA.PKCS15 as Vincent.RSA
14import qualified Crypto.PubKey.ECC.ECDSA as Vincent.ECDSA
15-- import Math.NumberTheory.Moduli
12 16
13import Data.OpenPGP.Util.Base 17import Data.OpenPGP.Util.Base
14 18
@@ -19,6 +23,14 @@ dsaKey k = Vincent.DSA.PublicKey
19 (keyParam 'y' k) 23 (keyParam 'y' k)
20 24
21 25
26{-
27applyCurve :: Vincent.ECDSA.CurveCommon -> Integer -> Integer
28applyCurve curve x = x*x*x + x*a + b
29 where
30 a = Vincent.ECDSA.ecc_a curve
31 b = Vincent.ECDSA.ecc_b curve
32-}
33
22-- | Verify a message signature 34-- | Verify a message signature
23verify :: 35verify ::
24 OpenPGP.Message -- ^ Keys that may have made the signature 36 OpenPGP.Message -- ^ Keys that may have made the signature
@@ -35,17 +47,28 @@ verifyOne keys sig over = fmap (const sig) $ maybeKey >>= verification >>= guard
35 where 47 where
36 verification = case OpenPGP.key_algorithm sig of 48 verification = case OpenPGP.key_algorithm sig of
37 OpenPGP.DSA -> dsaVerify 49 OpenPGP.DSA -> dsaVerify
50 OpenPGP.ECDSA -> ecdsaVerify
38 alg | alg `elem` [OpenPGP.RSA,OpenPGP.RSA_S] -> rsaVerify 51 alg | alg `elem` [OpenPGP.RSA,OpenPGP.RSA_S] -> rsaVerify
39 | otherwise -> const Nothing 52 | otherwise -> const Nothing
40 dsaVerify k = let k' = dsaKey k in 53 dsaVerify k = let k' = dsaKey k in
41 Just $ Vincent.DSA.verify (dsaTruncate k' . bhash) k' dsaSig over 54 Just $ Vincent.DSA.verify (dsaTruncate k' . bhash) k' dsaSig over
55 ecdsaVerify k = let k' = ecdsaKey k
56 r = Just $ Vincent.ECDSA.verify bhash k' ecdsaSig over
57 in r -- trace ("ecdsaVerify: "++show r) r
42 rsaVerify k = Just $ Vincent.RSA.verify desc (rsaKey k) over rsaSig 58 rsaVerify k = Just $ Vincent.RSA.verify desc (rsaKey k) over rsaSig
43 [rsaSig] = map (toStrictBS . LZ.drop 2 . encode) (OpenPGP.signature sig) 59 [rsaSig] = map (toStrictBS . LZ.drop 2 . encode) (OpenPGP.signature sig)
44 dsaSig = let [OpenPGP.MPI r, OpenPGP.MPI s] = OpenPGP.signature sig in 60 dsaSig = let [OpenPGP.MPI r, OpenPGP.MPI s] = OpenPGP.signature sig in
45 Vincent.DSA.Signature r s 61 Vincent.DSA.Signature r s
62 ecdsaSig = let [OpenPGP.MPI r, OpenPGP.MPI s] = OpenPGP.signature sig in
63 Vincent.ECDSA.Signature r s
46 dsaTruncate (Vincent.DSA.PublicKey (Vincent.DSA.Params _ _ q) _) = BS.take (integerBytesize q) 64 dsaTruncate (Vincent.DSA.PublicKey (Vincent.DSA.Params _ _ q) _) = BS.take (integerBytesize q)
65 {-
66 ecdsaTruncate (Vincent.ECDSA.PublicKey _ (Vincent.ECDSA.Point x y)) = BS.take (integerBytesize x
67 + integerBytesize y )
68 -}
47 bhash = hashBySymbol hash_algo . toLazyBS 69 bhash = hashBySymbol hash_algo . toLazyBS
48 desc = hashAlgoDesc hash_algo 70 desc = hashAlgoDesc hash_algo
49 hash_algo = OpenPGP.hash_algorithm sig 71 hash_algo = OpenPGP.hash_algorithm sig
50 maybeKey = OpenPGP.signature_issuer sig >>= find_key keys 72 maybeKey = OpenPGP.signature_issuer sig >>= find_key keys
73 -- in trace ("maybeKey="++show (fmap OpenPGP.key_algorithm r)) r
51 74
diff --git a/openpgp-util.cabal b/openpgp-util.cabal
index 5bc4bfb..ca02709 100644
--- a/openpgp-util.cabal
+++ b/openpgp-util.cabal
@@ -45,6 +45,7 @@ library
45 crypto-random >= 0.0.7, 45 crypto-random >= 0.0.7,
46 cryptohash >= 0.9.1, 46 cryptohash >= 0.9.1,
47 crypto-pubkey >= 0.2.3, 47 crypto-pubkey >= 0.2.3,
48 crypto-pubkey-types >= 0.4.1,
48 cipher-cast5 -any, 49 cipher-cast5 -any,
49 byteable, 50 byteable,
50 crypto-cipher-types >= 0.0.9, 51 crypto-cipher-types >= 0.0.9,