Commit 8f8a95be authored by Apollon Oikonomopoulos's avatar Apollon Oikonomopoulos
Browse files

Switch from haskell-crypto to haskell-cryptonite

Haskell-Crypto is broken with GHC 8.6[1][2], so switch over to cryptonite
which is the de-facto crypto library for Haskell nowadays.

[1] https://gitlab.haskell.org/ghc/ghc/issues/16406
[2] https://bugs.debian.org/945931
parent ce5c7172
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ Build-Depends: debhelper-compat (= 12),
 libghc-utf8-string-dev,
 libghc-deepseq-dev,
 libghc-hslogger-dev,
 libghc-crypto-dev,
 libghc-cryptonite-dev,
 libghc-text-dev,
 libghc-hinotify-dev (>= 0.3.10),
 libghc-base64-bytestring-dev (>= 1.0.0.0),
+120 −0
Original line number Diff line number Diff line
From: Apollon Oikonomopoulos <apoikos@dmesg.gr>
Date: Fri, 29 Nov 2019 18:16:19 +0200
Subject: Port Ganeti.Hash to cryptonite

There's a bug exposed by the combination of Crypto and GHC 8.6 that
results in an endless loop[1], caused by GHC 8.6 changing accumArray
from lazy to strict. The endless loop can be reproduced as follows:

 Prelude> :m +Data.HMAC
 Prelude Data.HMAC> hmac_sha1 [] []

Unfortunately Crypto was last updated in 2012 and seems to be largely
unmaintained, so at this point it's probably a good idea to switch our
HMAC implementation over to cryptonite, which is the de facto standard
for crypto in Haskell these days.

[1] https://gitlab.haskell.org/ghc/ghc/issues/16406

Signed-off-by: Apollon Oikonomopoulos <apoikos@dmesg.gr>
---
 INSTALL                     |  4 ++--
 cabal/ganeti.template.cabal |  2 +-
 configure.ac                |  2 +-
 src/Ganeti/Hash.hs          | 18 +++++-------------
 4 files changed, 9 insertions(+), 17 deletions(-)

diff --git a/INSTALL b/INSTALL
index 95f3019..d3585f9 100644
--- a/INSTALL
+++ b/INSTALL
@@ -173,7 +173,7 @@ Some of these are also available as package in Debian/Ubuntu::
                     libghc-parallel-dev \
                     libghc-utf8-string-dev libghc-curl-dev \
                     libghc-hslogger-dev \
-                    libghc-crypto-dev libghc-text-dev \
+                    libghc-cryptonite-dev libghc-text-dev \
                     libghc-hinotify-dev libghc-regex-pcre-dev \
                     libpcre3-dev \
                     libghc-attoparsec-dev libghc-vector-dev \
@@ -192,7 +192,7 @@ In Fedora, some of them are available via packages as well::
                     ghc-hslogger-devel ghc-text-devel \
                     ghc-regex-pcre-devel
 
-The most recent Fedora doesn't provide ``crypto``, ``inotify``. So these
+The most recent Fedora doesn't provide ``inotify``. So these
 need to be installed using ``cabal``.
 
 If using a distribution which does not provide these libraries, first
diff --git a/cabal/ganeti.template.cabal b/cabal/ganeti.template.cabal
index f3f4d91..1217cfe 100644
--- a/cabal/ganeti.template.cabal
+++ b/cabal/ganeti.template.cabal
@@ -45,6 +45,7 @@ library
     , array                         >= 0.4.0.0
     , bytestring                    >= 0.9.2.1
     , containers                    >= 0.4.2.1
+    , cryptonite                    >= 0.25
     , deepseq                       >= 1.3.0.0
     , directory                     >= 1.1.0.2
     , filepath                      >= 1.3.0.0
@@ -63,7 +64,6 @@ library
     , attoparsec                    >= 0.10.1.1   && < 0.14
     , base64-bytestring             >= 1.0.0.1    && < 1.1
     , case-insensitive              >= 0.4.0.1    && < 1.3
-    , Crypto                        >= 4.2.4      && < 4.3
     , curl                          >= 1.3.7      && < 1.4
     , hinotify                      >= 0.3.2      && < 0.5
     , hslogger                      >= 1.1.4      && < 1.3
diff --git a/configure.ac b/configure.ac
index d4519c5..d0101ea 100644
--- a/configure.ac
+++ b/configure.ac
@@ -679,7 +679,7 @@ AC_GHC_PKG_REQUIRE(attoparsec)
 AC_GHC_PKG_REQUIRE(vector)
 AC_GHC_PKG_REQUIRE(text)
 AC_GHC_PKG_REQUIRE(hinotify)
-AC_GHC_PKG_REQUIRE(Crypto)
+AC_GHC_PKG_REQUIRE(cryptonite)
 AC_GHC_PKG_REQUIRE(lifted-base)
 AC_GHC_PKG_REQUIRE(lens)
 AC_GHC_PKG_REQUIRE(regex-pcre)
diff --git a/src/Ganeti/Hash.hs b/src/Ganeti/Hash.hs
index f0065d8..19325d4 100644
--- a/src/Ganeti/Hash.hs
+++ b/src/Ganeti/Hash.hs
@@ -39,29 +39,21 @@ module Ganeti.Hash
   ) where
 
 import qualified Data.ByteString as B
+import qualified Data.ByteString.UTF8 as BU
+import Crypto.Hash.Algorithms
+import Crypto.MAC.HMAC
 import Data.Char
-import Data.HMAC (hmac_sha1)
-import qualified Data.Text as T
-import Data.Text.Encoding (encodeUtf8)
 import Data.Word
-import Text.Printf (printf)
 
 -- | Type alias for the hash key. This depends on the library being
 -- used.
 type HashKey = [Word8]
 
--- | Converts a string to a list of bytes.
-stringToWord8 :: String -> HashKey
-stringToWord8 = B.unpack . encodeUtf8 . T.pack
-
--- | Converts a list of bytes to a string.
-word8ToString :: HashKey -> String
-word8ToString = concatMap (printf "%02x")
-
 -- | Computes the HMAC for a given key/test and salt.
 computeMac :: HashKey -> Maybe String -> String -> String
 computeMac key salt text =
-  word8ToString . hmac_sha1 key . stringToWord8 $ maybe text (++ text) salt
+  let hashable = maybe text (++ text) salt
+  in show . hmacGetDigest $ (hmac (B.pack key) (BU.fromString hashable) :: HMAC SHA1)
 
 -- | Verifies the HMAC for a given message.
 verifyMac :: HashKey -> Maybe String -> String -> String -> Bool
+1 −0
Original line number Diff line number Diff line
@@ -6,3 +6,4 @@
0006-HTools.Graph-use-IntMap.foldr.patch
0007-Add-MonadFail-instances.patch
0008-Relax-dep-on-haskell-network.patch
0009-Port-Ganeti.Hash-to-cryptonite.patch