summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2019-11-14 19:04:32 -0500
committerJoe Crayne <joe@jerkface.net>2019-11-14 19:04:32 -0500
commit713295a4ac808cc4bb1eb1f7be78d79d70dc6cd1 (patch)
tree1c58ede41f76f295a42b6da431443bfb36e39e61
parent6252bdbd0531feaa6ac9e881dffe5c92b8b40197 (diff)
Enable generating cv25519 keys.
-rw-r--r--Data/OpenPGP/Util/Cv25519.hs14
-rw-r--r--Data/OpenPGP/Util/Decrypt.hs53
-rw-r--r--Data/OpenPGP/Util/DecryptSecretKey.hs40
-rw-r--r--Data/OpenPGP/Util/Gen.hs11
-rw-r--r--openpgp-util.cabal1
5 files changed, 75 insertions, 44 deletions
diff --git a/Data/OpenPGP/Util/Cv25519.hs b/Data/OpenPGP/Util/Cv25519.hs
index 4900b2f..d5ac641 100644
--- a/Data/OpenPGP/Util/Cv25519.hs
+++ b/Data/OpenPGP/Util/Cv25519.hs
@@ -26,7 +26,7 @@ import qualified Crypto.PubKey.Curve25519 as Cv25519
26import Crypto.Error 26import Crypto.Error
27import Crypto.Cipher.AES 27import Crypto.Cipher.AES
28import Crypto.Cipher.Types 28import Crypto.Cipher.Types
29import Data.OpenPGP.Util.DecryptSecretKey -- (withS2K, simpleUnCFB, Enciphered(..)) 29import Data.OpenPGP.Util.Decrypt -- (withS2K, simpleUnCFB, Enciphered(..))
30 30
31import Crypto.JOSE.AESKW 31import Crypto.JOSE.AESKW
32 32
@@ -229,3 +229,15 @@ decryptMessage ecdhkey asym encdta = do
229 b1 = BL.drop (2 + fromIntegral blksize) b0 229 b1 = BL.drop (2 + fromIntegral blksize) b0
230 (_,_, Message ps) <- either (const Nothing) Just $ decodeOrFail b1 230 (_,_, Message ps) <- either (const Nothing) Just $ decodeOrFail b1
231 return ps 231 return ps
232
233importSecretCv25519 :: Cv25519.SecretKey -> [(Char,MPI)]
234importSecretCv25519 k =
235 [ ('c', MPI oid_cv25519)
236 , ('l', MPI 128)
237 , ('n', MPI pub)
238 , ('f', MPI 0x40)
239 , ('d', MPI sec)
240 ]
241 where
242 pub = getBigNum $ BA.convert $ Cv25519.toPublic k
243 sec = getBigNumLE $ BA.convert k
diff --git a/Data/OpenPGP/Util/Decrypt.hs b/Data/OpenPGP/Util/Decrypt.hs
new file mode 100644
index 0000000..84bead5
--- /dev/null
+++ b/Data/OpenPGP/Util/Decrypt.hs
@@ -0,0 +1,53 @@
1{-# LANGUAGE RankNTypes, CPP #-}
2module Data.OpenPGP.Util.Decrypt where
3
4import qualified Data.ByteString.Lazy as LZ
5import Crypto.Error
6import qualified Crypto.Cipher.AES as Vincent
7import qualified Crypto.Cipher.Blowfish as Vincent
8import qualified Crypto.Cipher.Types as Vincent
9import Crypto.Cipher.Cast5 (CAST5_128)
10import Crypto.Cipher.ThomasToVincent
11import qualified Data.OpenPGP as OpenPGP
12import Data.OpenPGP.Util.Base
13
14
15-- decryption codec for withS2K
16simpleUnCFB :: (Vincent.BlockCipher k) => k -> Vincent.IV k -> LZ.ByteString -> LZ.ByteString
17simpleUnCFB k iv = padThenUnpad k (toLazyBS . Vincent.cfbDecrypt k iv . toStrictBS)
18
19withS2K' :: OpenPGP.SymmetricAlgorithm -> Maybe OpenPGP.S2K -> LZ.ByteString
20 -> (forall b. Vincent.BlockCipher b => b -> x) -> x
21withS2K' OpenPGP.AES128 s2k s f = f (string2key s2k s :: Vincent.AES128)
22withS2K' OpenPGP.AES192 s2k s f = f (string2key s2k s :: Vincent.AES192)
23withS2K' OpenPGP.AES256 s2k s f = f (string2key s2k s :: Vincent.AES256)
24withS2K' OpenPGP.Blowfish s2k s f = f (string2key s2k s :: Vincent.Blowfish128)
25withS2K' OpenPGP.CAST5 s2k s f = f (string2key s2k s :: ThomasToVincent CAST5_128)
26
27string2key :: (Vincent.BlockCipher k) => Maybe OpenPGP.S2K -> LZ.ByteString -> k
28string2key ms2k s = cipher
29 where
30#if defined(VERSION_cryptonite)
31 CryptoPassed cipher = Vincent.cipherInit k
32 k = toStrictBS $ LZ.take ksize $ maybe s (\s2k -> OpenPGP.string2key hashBySymbol s2k s) ms2k
33#else
34 cipher = Vincent.cipherInit k
35 Right k = Vincent.makeKey $ toStrictBS $
36 LZ.take ksize $ maybe s (\s2k -> OpenPGP.string2key hashBySymbol s2k s) ms2k
37#endif
38 ksize = case Vincent.cipherKeySize cipher of
39 Vincent.KeySizeFixed n -> fromIntegral n
40 Vincent.KeySizeEnum xs -> error $ "Unknown key size in string2key"
41 Vincent.KeySizeRange min max -> error $ "Unknown key size range in string2key"
42
43-- Apply a function f to a zero-padded bytestring s to a multiple
44-- of the blocksize for cyper k.
45-- Then drop the same number of bytes from the result of f.
46padThenUnpad :: (Vincent.BlockCipher k) => k -> (LZ.ByteString -> LZ.ByteString) -> LZ.ByteString -> LZ.ByteString
47padThenUnpad k f s = dropPadEnd (f padded)
48 where
49 dropPadEnd s = LZ.take (LZ.length s - padAmount) s
50 padded = s `LZ.append` LZ.replicate padAmount 0
51 padAmount = blksize - (LZ.length s `mod` blksize)
52 blksize = fromIntegral $ Vincent.blockSize k
53
diff --git a/Data/OpenPGP/Util/DecryptSecretKey.hs b/Data/OpenPGP/Util/DecryptSecretKey.hs
index a637b29..57dd8c3 100644
--- a/Data/OpenPGP/Util/DecryptSecretKey.hs
+++ b/Data/OpenPGP/Util/DecryptSecretKey.hs
@@ -27,6 +27,7 @@ import qualified Crypto.Cipher.AES as Vincent
27import qualified Crypto.Cipher.Blowfish as Vincent 27import qualified Crypto.Cipher.Blowfish as Vincent
28 28
29import qualified Crypto.Cipher.Types as Vincent 29import qualified Crypto.Cipher.Types as Vincent
30import Data.OpenPGP.Util.Decrypt
30 31
31#if defined(VERSION_cryptonite) 32#if defined(VERSION_cryptonite)
32import qualified Data.ByteArray as Bytes 33import qualified Data.ByteArray as Bytes
@@ -131,18 +132,6 @@ withS2K codec OpenPGP.Blowfish s2k s = withIV $ codec (string2key s2k s :: Vince
131withS2K codec OpenPGP.CAST5 s2k s = withIV $ codec (string2key s2k s :: ThomasToVincent CAST5_128) 132withS2K codec OpenPGP.CAST5 s2k s = withIV $ codec (string2key s2k s :: ThomasToVincent CAST5_128)
132withS2K codec algo _ _ = error $ "Unsupported symmetric algorithm : " ++ show algo ++ " in Data.OpenPGP.CryptoAPI.withS2K" 133withS2K codec algo _ _ = error $ "Unsupported symmetric algorithm : " ++ show algo ++ " in Data.OpenPGP.CryptoAPI.withS2K"
133 134
134withS2K' :: OpenPGP.SymmetricAlgorithm -> Maybe OpenPGP.S2K -> LZ.ByteString
135 -> (forall b. Vincent.BlockCipher b => b -> x) -> x
136withS2K' OpenPGP.AES128 s2k s f = f (string2key s2k s :: Vincent.AES128)
137withS2K' OpenPGP.AES192 s2k s f = f (string2key s2k s :: Vincent.AES192)
138withS2K' OpenPGP.AES256 s2k s f = f (string2key s2k s :: Vincent.AES256)
139withS2K' OpenPGP.Blowfish s2k s f = f (string2key s2k s :: Vincent.Blowfish128)
140withS2K' OpenPGP.CAST5 s2k s f = f (string2key s2k s :: ThomasToVincent CAST5_128)
141
142-- decryption codec for withS2K
143simpleUnCFB :: (Vincent.BlockCipher k) => k -> Vincent.IV k -> LZ.ByteString -> LZ.ByteString
144simpleUnCFB k iv = padThenUnpad k (toLazyBS . Vincent.cfbDecrypt k iv . toStrictBS)
145
146simpleCFB :: forall k g. (Vincent.BlockCipher k, RG g) => g -> k -> LZ.ByteString -> (LZ.ByteString, g) 135simpleCFB :: forall k g. (Vincent.BlockCipher k, RG g) => g -> k -> LZ.ByteString -> (LZ.ByteString, g)
147simpleCFB g k bs = ( padThenUnpad k (LZ.fromChunks . (ivbs:) . (:[]) . Vincent.cfbEncrypt k iv . toStrictBS) bs 136simpleCFB g k bs = ( padThenUnpad k (LZ.fromChunks . (ivbs:) . (:[]) . Vincent.cfbEncrypt k iv . toStrictBS) bs
148 , g' ) 137 , g' )
@@ -158,33 +147,6 @@ simpleCFB g k bs = ( padThenUnpad k (LZ.fromChunks . (ivbs:) . (:[]) . Vincent.c
158 _ = Vincent.constEqBytes z iv 147 _ = Vincent.constEqBytes z iv
159#endif 148#endif
160 149
161-- Apply a function f to a zero-padded bytestring s to a multiple
162-- of the blocksize for cyper k.
163-- Then drop the same number of bytes from the result of f.
164padThenUnpad :: (Vincent.BlockCipher k) => k -> (LZ.ByteString -> LZ.ByteString) -> LZ.ByteString -> LZ.ByteString
165padThenUnpad k f s = dropPadEnd (f padded)
166 where
167 dropPadEnd s = LZ.take (LZ.length s - padAmount) s
168 padded = s `LZ.append` LZ.replicate padAmount 0
169 padAmount = blksize - (LZ.length s `mod` blksize)
170 blksize = fromIntegral $ Vincent.blockSize k
171
172string2key :: (Vincent.BlockCipher k) => Maybe OpenPGP.S2K -> LZ.ByteString -> k
173string2key ms2k s = cipher
174 where
175#if defined(VERSION_cryptonite)
176 CryptoPassed cipher = Vincent.cipherInit k
177 k = toStrictBS $ LZ.take ksize $ maybe s (\s2k -> OpenPGP.string2key hashBySymbol s2k s) ms2k
178#else
179 cipher = Vincent.cipherInit k
180 Right k = Vincent.makeKey $ toStrictBS $
181 LZ.take ksize $ maybe s (\s2k -> OpenPGP.string2key hashBySymbol s2k s) ms2k
182#endif
183 ksize = case Vincent.cipherKeySize cipher of
184 Vincent.KeySizeFixed n -> fromIntegral n
185 Vincent.KeySizeEnum xs -> error $ "Unknown key size in string2key"
186 Vincent.KeySizeRange min max -> error $ "Unknown key size range in string2key"
187
188catchIO_ :: IO a -> IO a -> IO a 150catchIO_ :: IO a -> IO a -> IO a
189catchIO_ a h = Exception.catch a (\(_ :: IOException) -> h) 151catchIO_ a h = Exception.catch a (\(_ :: IOException) -> h)
190 152
diff --git a/Data/OpenPGP/Util/Gen.hs b/Data/OpenPGP/Util/Gen.hs
index ca3c684..c33ef1e 100644
--- a/Data/OpenPGP/Util/Gen.hs
+++ b/Data/OpenPGP/Util/Gen.hs
@@ -14,7 +14,9 @@ import qualified Crypto.PubKey.RSA as Vincent.RSA
14import qualified Crypto.PubKey.RSA.PKCS15 as Vincent.RSA 14import qualified Crypto.PubKey.RSA.PKCS15 as Vincent.RSA
15import qualified Crypto.PubKey.ECC.ECDSA as Vincent.ECDSA 15import qualified Crypto.PubKey.ECC.ECDSA as Vincent.ECDSA
16#if defined(VERSION_cryptonite) 16#if defined(VERSION_cryptonite)
17import qualified Crypto.PubKey.Curve25519 as Cv25519
17import qualified Crypto.PubKey.Ed25519 as Ed25519 18import qualified Crypto.PubKey.Ed25519 as Ed25519
19import Data.OpenPGP.Util.Cv25519
18import Data.OpenPGP.Util.Ed25519 20import Data.OpenPGP.Util.Ed25519
19import Control.Arrow (second) 21import Control.Arrow (second)
20import Data.Binary 22import Data.Binary
@@ -25,6 +27,7 @@ import Data.OpenPGP.Util.Base
25data GenerateKeyParams = GenRSA Int -- keysize 27data GenerateKeyParams = GenRSA Int -- keysize
26 | GenDSA (Maybe DSAParams) 28 | GenDSA (Maybe DSAParams)
27 | GenEd25519 29 | GenEd25519
30 | GenCv25519
28 deriving (Eq,Ord,Show) 31 deriving (Eq,Ord,Show)
29 32
30data DSAParams = DSAParams 33data DSAParams = DSAParams
@@ -121,10 +124,10 @@ generateKey' (GenDSA mbparams) g =
121generateKey' (GenEd25519 {}) g = withDRG g $ do 124generateKey' (GenEd25519 {}) g = withDRG g $ do
122 k <- Ed25519.generateSecretKey 125 k <- Ed25519.generateSecretKey
123 return $ importSecretEd25519 k 126 return $ importSecretEd25519 k
124 -- file:///usr/share/doc/libghc-cryptonite-doc/html/Crypto-PubKey-Ed25519.html#v:generateSecretKey 127generateKey' (GenCv25519 {}) g = withDRG g $ do
125 -- generateSecretKey :: MonadRandom m => m SecretKey 128 k <- Cv25519.generateSecretKey
126 -- n = public key used to verify signatures. 129 return $ importSecretCv25519 k
127 -- public_key_fields Ed25519 = ['c','l','x', 'y', 'n', 'f'] 130
128 131
129#endif 132#endif
130 133
diff --git a/openpgp-util.cabal b/openpgp-util.cabal
index 132cb05..055dde7 100644
--- a/openpgp-util.cabal
+++ b/openpgp-util.cabal
@@ -139,6 +139,7 @@ library
139 Data.OpenPGP.Util.Verify 139 Data.OpenPGP.Util.Verify
140 Data.OpenPGP.Util.Sign 140 Data.OpenPGP.Util.Sign
141 Data.OpenPGP.Util.Gen 141 Data.OpenPGP.Util.Gen
142 Data.OpenPGP.Util.Decrypt
142 Data.OpenPGP.Util.DecryptSecretKey 143 Data.OpenPGP.Util.DecryptSecretKey
143 Data.OpenPGP.Util.Ed25519 144 Data.OpenPGP.Util.Ed25519
144 build-depends: 145 build-depends: