packages feed

HsOpenSSL 0.11.2.4 → 0.11.3

raw patch · 6 files changed

+126/−57 lines, 6 filesdep ~HUnitPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: HUnit

API changes (from Hackage documentation)

- OpenSSL.RSA: fromDERPub :: ByteString -> Maybe RSAPubKey
- OpenSSL.RSA: toDERPub :: RSAKey k => k -> ByteString
+ OpenSSL.DER: fromDERPriv :: RSAKey k => ByteString -> Maybe k
+ OpenSSL.DER: fromDERPub :: ByteString -> Maybe RSAPubKey
+ OpenSSL.DER: toDERPriv :: RSAKeyPair -> ByteString
+ OpenSSL.DER: toDERPub :: RSAKey k => k -> ByteString

Files

ChangeLog view
@@ -1,3 +1,13 @@+2016-10-14  Vladimir Shabanov  <vshabanoff@gmail.com>++	* HsOpenSSL.cabal (Version): Bump version to 0.11.3++	* HsOpenSSL.cabal (Build-Depends): Bump HUnit upper bound,++	* OpenSSL/RSA.hsc, OpenSSL/DER.hsc: moved DER function from RSA to DER+	module. Added encoding/decoding of private keys in ASN.1 DER.+	by @shak-mar (#12).+ 2016-10-08  Vladimir Shabanov  <vshabanoff@gmail.com>  	* HsOpenSSL.cabal (Version): Bump version to 0.11.2.4
HsOpenSSL.cabal view
@@ -12,7 +12,7 @@     <http://hackage.haskell.org/package/tls>, which is a pure Haskell     implementation of SSL.     .-Version:       0.11.2.4+Version:       0.11.3 License:       PublicDomain License-File:  COPYING Author:        Adam Langley, Mikhail Vorozhtsov, PHO, Taru Karttunen@@ -100,6 +100,7 @@     Exposed-Modules:         OpenSSL         OpenSSL.BN+        OpenSSL.DER         OpenSSL.EVP.Base64         OpenSSL.EVP.Cipher         OpenSSL.EVP.Digest@@ -148,7 +149,7 @@     Main-Is: Test/OpenSSL/Cipher.hs     Build-Depends:         HsOpenSSL,-        HUnit                >= 1.0 && < 1.4,+        HUnit                >= 1.0 && < 1.5,         base                 >= 4.4 && < 5,         bytestring           >= 0.9 && < 0.11,         test-framework       >= 0.8 && < 0.9,@@ -163,7 +164,7 @@     Main-Is: Test/OpenSSL/DSA.hs     Build-Depends:         HsOpenSSL,-        HUnit                >= 1.0 && < 1.4,+        HUnit                >= 1.0 && < 1.5,         base                 >= 4.4 && < 5,         bytestring           >= 0.9 && < 0.11,         test-framework       >= 0.8 && < 0.9,@@ -173,12 +174,12 @@     GHC-Options:         -Wall -Test-Suite test-rsa+Test-Suite test-der     Type:    exitcode-stdio-1.0-    Main-Is: Test/OpenSSL/RSA.hs+    Main-Is: Test/OpenSSL/DER.hs     Build-Depends:         HsOpenSSL,-        HUnit                >= 1.0 && < 1.4,+        HUnit                >= 1.0 && < 1.5,         base                 >= 4.4 && < 5,         bytestring           >= 0.9 && < 0.11,         test-framework       >= 0.8 && < 0.9,@@ -193,7 +194,7 @@     Main-Is: Test/OpenSSL/EVP/Base64.hs     Build-Depends:         HsOpenSSL,-        HUnit                >= 1.0 && < 1.4,+        HUnit                >= 1.0 && < 1.5,         base                 >= 4.4 && < 5,         bytestring           >= 0.9 && < 0.11,         test-framework       >= 0.8 && < 0.9,
+ OpenSSL/DER.hsc view
@@ -0,0 +1,89 @@+{-# LANGUAGE ForeignFunctionInterface #-}+-- |Encoding and decoding of RSA keys using the ASN.1 DER format+module OpenSSL.DER+    ( toDERPub+    , fromDERPub+    , toDERPriv+    , fromDERPriv+    )+    where++#if !MIN_VERSION_base(4,8,0)+import Control.Applicative ((<$>))+#endif+import           OpenSSL.RSA                (RSA, RSAKey, RSAKeyPair, RSAPubKey,+                                             absorbRSAPtr, withRSAPtr)++import           Data.ByteString            (ByteString)+import qualified Data.ByteString            as B  (useAsCStringLen)+import qualified Data.ByteString.Internal   as BI (createAndTrim)+import           Foreign.Ptr                (Ptr, nullPtr)+import           Foreign.C.String           (CString)+import           Foreign.C.Types            (CLong(..), CInt(..))+import           Foreign.Marshal.Alloc      (alloca)+import           Foreign.Storable           (poke)+import           GHC.Word                   (Word8)+import           System.IO.Unsafe           (unsafePerformIO)++type CDecodeFun = Ptr (Ptr RSA) -> Ptr CString -> CLong -> IO (Ptr RSA)+type CEncodeFun = Ptr RSA -> Ptr (Ptr Word8) -> IO CInt++foreign import ccall unsafe "d2i_RSAPublicKey"+  _fromDERPub :: CDecodeFun++foreign import ccall unsafe "i2d_RSAPublicKey"+  _toDERPub :: CEncodeFun++foreign import ccall unsafe "d2i_RSAPrivateKey"+  _fromDERPriv :: CDecodeFun++foreign import ccall unsafe "i2d_RSAPrivateKey"+  _toDERPriv :: CEncodeFun++-- | Generate a function that decodes a key from ASN.1 DER format+makeDecodeFun :: RSAKey k => CDecodeFun -> ByteString -> Maybe k+makeDecodeFun fun bs = unsafePerformIO . usingConvedBS $ \(csPtr, ci) -> do+  -- When you pass a null pointer to this function, it will allocate the memory+  -- space required for the RSA key all by itself.  It will be freed whenever+  -- the haskell object is garbage collected, as they are stored in ForeignPtrs+  -- internally.+  rsaPtr <- fun nullPtr csPtr ci+  if rsaPtr == nullPtr then return Nothing else absorbRSAPtr rsaPtr+  where usingConvedBS io = B.useAsCStringLen bs $ \(cs, len) ->+          alloca $ \csPtr -> poke csPtr cs >> io (csPtr, fromIntegral len)++-- | Generate a function that encodes a key in ASN.1 DER format+makeEncodeFun :: RSAKey k => CEncodeFun -> k -> ByteString+makeEncodeFun fun k = unsafePerformIO $ do+  -- When you pass a null pointer to this function, it will only compute the+  -- required buffer size.  See https://www.openssl.org/docs/faq.html#PROG3+  requiredSize <- withRSAPtr k $ flip fun nullPtr+  -- It’s too sad BI.createAndTrim is considered internal, as it does a great+  -- job here.  See https://hackage.haskell.org/package/bytestring-0.9.1.4/docs/Data-ByteString-Internal.html#v%3AcreateAndTrim+  BI.createAndTrim (fromIntegral requiredSize) $ \ptr ->+    alloca $ \pptr ->+      (fromIntegral <$>) . withRSAPtr k $ \key ->+        poke pptr ptr >> fun key pptr++-- | Dump a public key to ASN.1 DER format+toDERPub :: RSAKey k+         => k          -- ^ You can pass either 'RSAPubKey' or 'RSAKeyPair'+                       --   because both contain the necessary information.+         -> ByteString -- ^ The public key information encoded in ASN.1 DER+toDERPub = makeEncodeFun _toDERPub++-- | Parse a public key from ASN.1 DER format+fromDERPub :: ByteString -> Maybe RSAPubKey+fromDERPub = makeDecodeFun _fromDERPub++-- | Dump a private key to ASN.1 DER format+toDERPriv :: RSAKeyPair -> ByteString+toDERPriv = makeEncodeFun _toDERPriv++-- | Parse a private key from ASN.1 DER format+fromDERPriv :: RSAKey k+            => ByteString -- ^ The private key information encoded in ASN.1 DER+            -> Maybe k    -- ^ This can return either 'RSAPubKey' or+                          --   'RSAKeyPair' because there’s sufficient+                          --   information for both.+fromDERPriv = makeDecodeFun _fromDERPriv
OpenSSL/RSA.hsc view
@@ -24,9 +24,6 @@     , rsaIQMP     , rsaCopyPublic     , rsaKeyPairFinalize -- private-      -- * DER encoding-    , fromDERPub-    , toDERPub     )     where #include "HsOpenSSL.h"@@ -34,21 +31,16 @@ #if !MIN_VERSION_base(4,8,0) import Control.Applicative ((<$>)) #endif-import Data.ByteString (ByteString)-import qualified Data.ByteString as B (useAsCStringLen)-import qualified Data.ByteString.Internal as BI (createAndTrim) import Data.Typeable-import Foreign.C.String (CString)+ #if MIN_VERSION_base(4,5,0)-import Foreign.C.Types (CInt(..), CLong(..))+import Foreign.C.Types (CInt(..)) #else-import Foreign.C.Types (CInt, CLong)+import Foreign.C.Types (CInt) #endif import Foreign.ForeignPtr (ForeignPtr, finalizeForeignPtr, newForeignPtr, withForeignPtr)-import Foreign.Marshal.Alloc (alloca) import Foreign.Ptr (FunPtr, Ptr, freeHaskellFunPtr, nullFunPtr, nullPtr) import Foreign.Storable (Storable(..))-import GHC.Word (Word8) import OpenSSL.BN import OpenSSL.Utils import System.IO.Unsafe (unsafePerformIO)@@ -244,31 +236,6 @@ -- |@'rsaIQMP' privkey@ returns @q^-1 mod p@ of the key. rsaIQMP :: RSAKeyPair -> Maybe Integer rsaIQMP = peekMI (#peek RSA, iqmp)--{- DER encoding ------------------------------------------------------------- -}--foreign import ccall unsafe "d2i_RSAPublicKey"-        _fromDERPub :: Ptr (Ptr RSA) -> Ptr CString -> CLong -> IO (Ptr RSA)--foreign import ccall unsafe "i2d_RSAPublicKey"-        _toDERPub :: Ptr RSA -> Ptr (Ptr Word8) -> IO CInt---- |Parse a public key from ASN.1 DER format-fromDERPub :: ByteString -> Maybe RSAPubKey-fromDERPub bs = unsafePerformIO . usingConvedBS $ \(csPtr, ci) -> do-    rsaPtr <- _fromDERPub nullPtr csPtr ci-    if rsaPtr == nullPtr then return Nothing else absorbRSAPtr rsaPtr-    where usingConvedBS io = B.useAsCStringLen bs $ \(cs, len) ->-              alloca $ \csPtr -> poke csPtr cs >> io (csPtr, fromIntegral len)---- |Dump a public key to ASN.1 DER format-toDERPub :: RSAKey k => k -> ByteString-toDERPub k = unsafePerformIO $ do-    requiredSize <- withRSAPtr k $ flip _toDERPub nullPtr-    BI.createAndTrim (fromIntegral requiredSize) $ \ptr ->-        alloca $ \pptr ->-            (fromIntegral <$>) $ withRSAPtr k $ \key ->-                poke pptr ptr >> _toDERPub key pptr  {- instances ---------------------------------------------------------------- -} 
+ Test/OpenSSL/DER.hs view
@@ -0,0 +1,16 @@+module Main (main) where++import OpenSSL.RSA+import OpenSSL.DER+import qualified Test.Framework as TF+import qualified Test.Framework.Providers.HUnit as TF+import Test.HUnit++test_encodeDecodeEqual :: Test+test_encodeDecodeEqual = TestCase $ do+  keyPair <- generateRSAKey 1024 3 Nothing+  pubKey <- rsaCopyPublic keyPair+  assertEqual "encodeDecode" (Just pubKey) (fromDERPub (toDERPub keyPair))++main :: IO ()+main = TF.defaultMain $ TF.hUnitTestToTests test_encodeDecodeEqual
− Test/OpenSSL/RSA.hs
@@ -1,14 +0,0 @@-module Main (main) where-import OpenSSL.RSA-import qualified Test.Framework as TF-import qualified Test.Framework.Providers.HUnit as TF-import Test.HUnit--test_encodeDecodeEqual :: Test-test_encodeDecodeEqual = TestCase $ do-  keyPair <- generateRSAKey 1024 3 Nothing-  pubKey <- rsaCopyPublic keyPair-  assertEqual "encodeDecode" (Just pubKey) (fromDERPub (toDERPub keyPair))--main :: IO ()-main = TF.defaultMain $ TF.hUnitTestToTests test_encodeDecodeEqual