Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Fast C implementation of safeEq #1

Closed
wants to merge 1 commit into from

2 participants

@meteficha

On my computer, the C implementation is 1.6x faster for 32-byte strings and 24x faster for 10-kbyte strings.

Sorry about the whitespace changes, I still don't know how to deal with them in git.

@meteficha meteficha Implement safeEq in C for greater performance.
On my computer, the C implementation is 1.6x faster for 32-byte strings and 24x faster for 10-kbyte strings.
f6e947d
@TomMD TomMD closed this
@TomMD
Owner

I merged this manually - thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Oct 3, 2011
  1. @meteficha

    Implement safeEq in C for greater performance.

    meteficha authored
    On my computer, the C implementation is 1.6x faster for 32-byte strings and 24x faster for 10-kbyte strings.
This page is out of date. Refresh to see the latest.
View
25 Crypto/Classes.hs
@@ -2,9 +2,9 @@
{-|
Maintainer: Thomas.DuBuisson@gmail.com
Stability: beta
- Portability: portable
+ Portability: portable
-This is the heart of the crypto-api package. By making (or having)
+This is the heart of the crypto-api package. By making (or having)
an instance of Hash, AsymCipher, BlockCipher or StreamCipher you provide (or obtain)
access to any infrastructure built on these primitives include block cipher modes
of operation, hashing, hmac, signing, etc. These classes allow users to build
@@ -13,7 +13,7 @@ as changing a type signature.
-}
module Crypto.Classes
- (
+ (
-- * Hash class and helper functions
Hash(..)
, hash
@@ -40,12 +40,15 @@ import Data.Serialize
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString as B
import qualified Data.ByteString.Internal as I
+import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
import Data.Bits ((.|.), xor)
import Data.List (foldl')
import Data.Word (Word64)
import Data.Tagged
import Crypto.Types
import Crypto.Random
+import Foreign (Ptr, unsafePerformIO)
+import Foreign.C (CChar, CInt)
import System.Entropy
-- |The Hash class is intended as the generic interface
@@ -227,9 +230,25 @@ for t _ = unTagged t
-- otherwise you may leave a significant security hole
-- (cf. <http://codahale.com/a-lesson-in-timing-attacks/>).
safeEq :: B.ByteString -> B.ByteString -> Bool
+-- Fast C implementation.
+safeEq s1 s2 =
+ unsafePerformIO $
+ unsafeUseAsCStringLen s1 $ \(s1_ptr, s1_len) ->
+ unsafeUseAsCStringLen s2 $ \(s2_ptr, s2_len) ->
+ if s1_len /= s2_len
+ then return False
+ else (== 0) `fmap` c_safeEq s1_ptr s2_ptr (fromIntegral s1_len)
+
+foreign import ccall unsafe
+ c_safeEq :: Ptr CChar -> Ptr CChar -> CInt -> IO CInt
+
+{-
+-- Haskell only implementation.
safeEq s1 s2 =
B.length s1 == B.length s2 &&
foldl' (.|.) 0 (B.zipWith xor s1 s2) == 0
+-}
+
-- | Like 'safeEq', safeCompare can be used to compare two
-- bytestrings in a way that is less suceptible to timing
View
7 c_impl/misc.c
@@ -0,0 +1,7 @@
+/* Fast C implementation of a safe string equality test. */
+int c_safeEq(char *x, char *y, int length) {
+ int ret = 0, i;
+ for (i = 0; i < length; i++)
+ ret = ret | x[i] ^ y[i];
+ return ret;
+}
View
4 c_impl/misc.h
@@ -0,0 +1,4 @@
+#ifndef CRYPTO_API_MISC_H
+#define CRYPTO_API_MISC_H
+int c_safeEq(char *x, char *y, int length);
+#endif
View
5 crypto-api.cabal
@@ -24,6 +24,9 @@ stability: stable
build-type: Simple
cabal-version: >= 1.6
tested-with: GHC == 7.0.3
+extra-source-files:
+ c_impl/misc.c
+ c_impl/misc.h
Library
@@ -36,6 +39,8 @@ Library
hs-source-dirs:
exposed-modules: Crypto.Classes, Crypto.Types, Crypto.HMAC, Crypto.Modes, Crypto.Random, Crypto.Padding
other-modules: Crypto.Util, Crypto.CPoly
+ extensions: ForeignFunctionInterface
+ c-sources: c_impl/misc.c
source-repository head
type: git
Something went wrong with that request. Please try again.