peyotls-0.1.6.10: Pretty Easy YOshikuni-made TLS library
Currently implement the TLS1.2 protocol (RFC 5246, RFC 4492) only, and support the following cipher suites.
- TLS_RSA_WITH_AES_128_CBC_SHA
- TLS_RSA_WITH_AES_128_CBC_SHA256
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
implement the following curves
- SEC p256r1
And support client certificate with the following algorithms.
- RSA with SHA256
- ECDSA with SHA256
And support secure renegotiation (RFC 5746)
Currently not implement the following features.
- session resumption (RFC 5077)
- curves other than SEC p256r1
Server sample
- file: examples/simpleServer.hs
localhost.key: key file
-----BEGIN RSA PRIVATE KEY----- ... -----END RSA PRIVATE KEY-----
localhost.crt: certificate file
-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----
examples/simpleServer.hs
extensions
- OverloadedStrings
- PackageImports
import Control.Applicative import Control.Monad import "monads-tf" Control.Monad.State import Control.Concurrent import Data.HandleLike import Network import Network.PeyoTLS.Server import Network.PeyoTLS.ReadFile import "crypto-random" Crypto.Random import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as BSC main :: IO () main = do k <- readKey "localhost.key" c <- readCertificateChain ["localhost.crt"] g0 <- cprgCreate <$> createEntropyPool :: IO SystemRNG soc <- listenOn $ PortNumber 443 void . (`runStateT` g0) . forever $ do (h, _, _) <- liftIO $ accept soc g <- StateT $ return . cprgFork liftIO . forkIO . (`run` g) $ do p <- open h ["TLS_RSA_WITH_AES_128_CBC_SHA"] [(k, c)] Nothing doUntil BS.null (hlGetLine p) >>= liftIO . mapM_ BSC.putStrLn hlPut p $ BS.concat [ "HTTP/1.1 200 OK\r\n", "Transfer-Encoding: chunked\r\n", "Content-Type: text/plain\r\n\r\n", "5\r\nHello0\r\n\r\n" ] hlClose p doUntil :: Monad m => (a -> Bool) -> m a -> m [a] doUntil p rd = rd >>= \x -> (if p x then return . (: []) else (`liftM` doUntil p rd) . (:)) x
Client sample (only show HTTP header)
- file: examples/simpleClient.hs
cacert.pem: self-signed root certificate to validate server
-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----
examples/simpleClient.hs
extensions
- OverloadedStrings
- PackageImports
import Control.Applicative import Control.Monad import "monads-tf" Control.Monad.Trans import Data.HandleLike import Network import Network.PeyoTLS.ReadFile import Network.PeyoTLS.Client import "crypto-random" Crypto.Random import qualified Data.ByteString.Char8 as BSC main :: IO () main = do ca <- readCertificateStore ["cacert.pem"] h <- connectTo "localhost" $ PortNumber 443 g <- cprgCreate <$> createEntropyPool :: IO SystemRNG (`run` g) $ do p <- open' h "localhost" ["TLS_RSA_WITH_AES_128_CBC_SHA"] [] ca nms <- getNames p hlPut p "GET / HTTP/1.1 \r\n" hlPut p "Host: localhost\r\n\r\n" doUntil BSC.null (hlGetLine p) >>= liftIO . mapM_ BSC.putStrLn hlClose p doUntil :: Monad m => (a -> Bool) -> m a -> m [a] doUntil p rd = rd >>= \x -> (if p x then return . (: []) else (`liftM` doUntil p rd) . (:)) x
Client certificate server
- file: examples/clcertServer.hs
% diff examples/simpleServer.hs examples/clcertServer.hs 19a20 > ca <- readCertificateStore ["cacert.pem"] 27c28 < Nothing --- > $ Just ca
Client certificate client (RSA certificate)
- file: examples/clcertClient.hs
% diff examples/simpleClient.hs examples/clcertClient.hs 15a16,17 > rk <- readKey "client_rsa.key" > rc <- readCertificateChain ["client_rsa.crt"] 20c22 < p <- open' h "localhost" ["TLS_RSA_WITH_AES_128_CBC_SHA"] [] ca --- > p <- open' h "localhost" ["TLS_RSA_WITH_AES_128_CBC_SHA"] [(rk, rc)] ca
Client certificate client (ECDSA or RSA certificate)
- file: examples/clcertEcdsaClient.hs
% diff examples/clcertClient.hs examples/clcertEcdsaClient.hs 17a18,19 > ek <- readKey "client_ecdsa.key" > ec <- readCertificateChain ["client_ecdsa.crt"] 22c24 < p <- open' h "localhost" ["TLS_RSA_WITH_AES_128_CBC_SHA"] [(rk, rc)] ca --- > p <- open' h "localhost" ["TLS_RSA_WITH_AES_128_CBC_SHA"] [(ek, ec), (rk, rc)] ca
ECC server (use ECC or RSA depending on client)
- file: examples/eccServer.hs
% diff examples/simpleServer.hs examples/eccServer.hs 15a16,26 > cipherSuites :: [CipherSuite] > cipherSuites = [ > "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", > "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", > "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", > "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", > "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", > "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", > "TLS_RSA_WITH_AES_128_CBC_SHA256", > "TLS_RSA_WITH_AES_128_CBC_SHA" ] > 18,19c29,32 < k <- readKey "localhost.key" < c <- readCertificateChain ["localhost.crt"] --- > rk <- readKey "localhost.key" > rc <- readCertificateChain ["localhost.crt"] > ek <- readKey "localhost_ecdsa.key" > ec <- readCertificateChain ["localhost_ecdsa.crt"] 26c39 < p <- open h ["TLS_RSA_WITH_AES_128_CBC_SHA"] [(k, c)] --- > p <- open h cipherSuites [(rk, rc), (ek, ec)]
ECC client (use ECC or RSA depending on server)
- file: examples/eccClient.hs
% diff examples/simpleClient.hs examples/eccClient.hs 13a14,24 > cipherSuites :: [CipherSuite] > cipherSuites = [ > "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", > "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", > "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", > "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", > "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", > "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", > "TLS_RSA_WITH_AES_128_CBC_SHA256", > "TLS_RSA_WITH_AES_128_CBC_SHA" ] > 20c31 < p <- open' h "localhost" ["TLS_RSA_WITH_AES_128_CBC_SHA"] [] ca --- > p <- open' h "localhost" cipherSuites [] ca