diff options
author | Stephen Paul Weber <singpolyma@singpolyma.net> | 2011-08-10 19:14:14 -0500 |
---|---|---|
committer | Stephen Paul Weber <singpolyma@singpolyma.net> | 2011-08-10 19:14:14 -0500 |
commit | 446ba2e70da76d004f955876dba0d060dbe9e0a0 (patch) | |
tree | 992a2aad6b988246a804695c6045b4f7427f01cb /Data/OpenPGP | |
parent | 18ef79440155b80414423819888f76fb3bf18469 (diff) |
Ability to sign a message with RSA
Diffstat (limited to 'Data/OpenPGP')
-rw-r--r-- | Data/OpenPGP/Crypto.hs | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/Data/OpenPGP/Crypto.hs b/Data/OpenPGP/Crypto.hs index fee1d55..d4d08c0 100644 --- a/Data/OpenPGP/Crypto.hs +++ b/Data/OpenPGP/Crypto.hs | |||
@@ -4,13 +4,15 @@ | |||
4 | -- The recommended way to import this module is: | 4 | -- The recommended way to import this module is: |
5 | -- | 5 | -- |
6 | -- > import qualified Data.OpenPGP.Crypto as OpenPGP | 6 | -- > import qualified Data.OpenPGP.Crypto as OpenPGP |
7 | module Data.OpenPGP.Crypto (verify, fingerprint) where | 7 | module Data.OpenPGP.Crypto (sign, verify, fingerprint) where |
8 | 8 | ||
9 | import Data.Word | 9 | import Data.Word |
10 | import Data.List (find) | ||
10 | import Data.Map ((!)) | 11 | import Data.Map ((!)) |
11 | import qualified Data.ByteString.Lazy as LZ | 12 | import qualified Data.ByteString.Lazy as LZ |
12 | 13 | ||
13 | import Data.Binary | 14 | import Data.Binary |
15 | import Codec.Utils (fromOctets) | ||
14 | import qualified Codec.Encryption.RSA as RSA | 16 | import qualified Codec.Encryption.RSA as RSA |
15 | import qualified Data.Digest.MD5 as MD5 | 17 | import qualified Data.Digest.MD5 as MD5 |
16 | import qualified Data.Digest.SHA1 as SHA1 | 18 | import qualified Data.Digest.SHA1 as SHA1 |
@@ -91,3 +93,48 @@ verify keys message sigidx = | |||
91 | sig = sigs !! sigidx | 93 | sig = sigs !! sigidx |
92 | (sigs, (OpenPGP.LiteralDataPacket {OpenPGP.content = dta}):_) = | 94 | (sigs, (OpenPGP.LiteralDataPacket {OpenPGP.content = dta}):_) = |
93 | OpenPGP.signatures_and_data message | 95 | OpenPGP.signatures_and_data message |
96 | |||
97 | -- | Sign a message. Only supports RSA keys for now. | ||
98 | sign :: OpenPGP.Message -- ^ SecretKeys, one of which will be used | ||
99 | -> OpenPGP.Message -- ^ Message containing LiteralData to sign | ||
100 | -> OpenPGP.HashAlgorithm -- ^ HashAlgorithm to use is signature | ||
101 | -> String -- ^ KeyID of key to choose or @[]@ for first | ||
102 | -> Integer -- ^ Timestamp to put in signature | ||
103 | -> OpenPGP.Message | ||
104 | sign keys message hsh keyid timestamp = | ||
105 | OpenPGP.Message $ (sig' { | ||
106 | OpenPGP.signature = OpenPGP.MPI $ toNum $ reverse final, | ||
107 | OpenPGP.hash_head = toNum $ take 2 final | ||
108 | }):m | ||
109 | where | ||
110 | -- toNum has explicit param so that it can remain polymorphic | ||
111 | toNum l = fromOctets (256::Integer) l | ||
112 | final = RSA.decrypt (n, d) encoded | ||
113 | encoded = emsa_pkcs1_v1_5_encode dta (length n) hsh | ||
114 | (n, d) = (keyfield_as_octets k 'n', keyfield_as_octets k 'd') | ||
115 | dta = LZ.unpack $ LZ.append | ||
116 | (OpenPGP.content dataP) (OpenPGP.trailer sig') | ||
117 | sig' = sig { | ||
118 | OpenPGP.trailer = OpenPGP.calculate_signature_trailer sig | ||
119 | } | ||
120 | sig = OpenPGP.SignaturePacket { | ||
121 | OpenPGP.version = 4, | ||
122 | OpenPGP.key_algorithm = OpenPGP.RSA, | ||
123 | OpenPGP.hash_algorithm = hsh, | ||
124 | OpenPGP.signature_type = stype, | ||
125 | OpenPGP.hashed_subpackets = [ | ||
126 | OpenPGP.SignatureCreationTimePacket $ fromIntegral timestamp, | ||
127 | OpenPGP.IssuerPacket keyid' | ||
128 | ], | ||
129 | OpenPGP.unhashed_subpackets = [], | ||
130 | OpenPGP.signature = undefined, | ||
131 | OpenPGP.trailer = undefined, | ||
132 | OpenPGP.hash_head = undefined | ||
133 | } | ||
134 | keyid' = reverse $ take 16 $ reverse $ fingerprint k | ||
135 | stype = if OpenPGP.format dataP == 'b' then 0x00 else 0x01 | ||
136 | Just k = find_key keys keyid | ||
137 | Just dataP = find isLiteralData m | ||
138 | OpenPGP.Message m = message | ||
139 | isLiteralData (OpenPGP.LiteralDataPacket {}) = True | ||
140 | isLiteralData _ = False | ||