Use the idiom below to import Crypto.Random, due to a bug in iHaskell with the extension PackageImports


In [21]:
:ext OverloadedStrings
:!rm himports.hs
:!echo "{-# LANGUAGE PackageImports #-}" >> himports.hs
:!echo "module MouseBoxImports( module Crypto.Random ) where" >> himports.hs
:!echo "import  \"crypto-api\" Crypto.Random" >> himports.hs
:load himports







In [22]:
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as LB

In [23]:
import Codec.Crypto.RSA.Pure

In [24]:
g <- newGenIO :: IO SystemRandom

In [25]:
:info SystemRandom



In [26]:
let Right (public_key, private_key, g') = generateKeyPair g 2048

In [27]:
let Codec.Crypto.RSA.Pure.PublicKey public_size public_n public_e =  public_key

In [28]:
import Data.X509
import Data.ASN1.OID
import Data.ASN1.Types.String
import Data.Hourglass.Types
import Crypto.PubKey.RSA.Types

import qualified Data.Binary as Bn

In [29]:
stringize :: B.ByteString -> ASN1CharacterString 
stringize s = ASN1CharacterString IA5 s

In [30]:
:type PubKeyRSA $ Crypto.PubKey.RSA.Types.PublicKey public_size public_n public_e


PubKeyRSA $ Crypto.PubKey.RSA.Types.PublicKey public_size public_n public_e :: PubKey

In [31]:
pubkeyToAlg . PubKeyRSA $ Crypto.PubKey.RSA.Types.PublicKey public_size public_n public_e


PubKeyALG_RSA

In [32]:
publicKeyHasher :: Codec.Crypto.RSA.Pure.PublicKey -> B.ByteString
publicKeyHasher pk = LB.toStrict . LB.take 20 . Bn.encode $ pk

In [33]:
let 
  ca_common_name = "MouseBox Testing Cert. Authority # affewx "
  pubkey_to_use = PubKeyRSA $ Crypto.PubKey.RSA.Types.PublicKey public_size public_n public_e
  ca_dn = DistinguishedName [
        (getObjectID DnCommonName, stringize ca_common_name),
        (getObjectID DnCountry, stringize "SE"),
        (getObjectID DnOrganization, stringize "MouseBox by Zunzun AB"),
        (getObjectID DnOrganizationUnit, stringize "Testing")
        ]
  a_cert =  Certificate {
      certVersion = 2 -- There are three different versions of X.509. 
      -- The certificate has to claim what version it uses. 
      -- So you'll find this Version: field in the certificate. 
      -- The most recent version is 3 and this is the most used version.
      -- X.509 version 3 defines extensions. 
      -- So for example, they are used for certificate chains.
     , certSerial = 1
     , certSignatureAlg = SignatureALG HashSHA384 (pubkeyToAlg pubkey_to_use)
     , certIssuerDN = ca_dn
     , certValidity = (
         DateTime {dtDate = Date 2015 January 1, dtTime = TimeOfDay 0 0 0 0},
         DateTime {dtDate = Date 2025 December 31, dtTime = TimeOfDay 23 59 0 0}
         )
     , certSubjectDN = ca_dn
     , certPubKey = PubKeyRSA $ Crypto.PubKey.RSA.Types.PublicKey public_size public_n public_e
     -- TODO: We need to set a few extensions here....
     , certExtensions = Extensions (Just
         -- The set of extensions below is specific to CAs
         [
             extensionEncode True {-Critical-} (ExtKeyUsage [KeyUsage_keyCertSign]),
             extensionEncode True              (ExtBasicConstraints True 
                 -- The field below says that leaf certificates must be signed by this one.
                 -- A little bit in the way of extra-security...
                 (Just 0)
             ),
             extensionEncode True               (ExtSubjectKeyId . publicKeyHasher $ public_key )
         ]
       )
    }

In [34]:
hereSign :: B.ByteString -> (B.ByteString, SignatureALG, ())
hereSign stuff_to_sign = let
    Right  bs_sign = rsassa_pkcs1_v1_5_sign hashSHA384 private_key . LB.fromStrict $ stuff_to_sign
  in (LB.toStrict bs_sign, SignatureALG HashSHA384 PubKeyALG_RSA, () )

In [35]:
let (signed_exact_obj, _) = objectToSignedExact hereSign a_cert

In [36]:
B.writeFile "a_cert.der" $ encodeSignedObject signed_exact_obj




In [37]:
import Data.PEM

In [38]:
let 
   pem_formatted = PEM {
      pemName = "CERTIFICATE",
      pemHeader = [],
      pemContent = encodeSignedObject signed_exact_obj
      }
B.writeFile "a_cert.pem" . pemWriteBS $ pem_formatted

In [39]:
:!openssl verify -check_ss_sig -trusted a_cert.pem  a_cert.pem


a_cert.pem: OK

In [ ]: