{-# LANGUAGE OverloadedStrings #-}

module Algorithms
  ( hs512
  , rs256
  , rs512
  , es256
  , es512
  , jwkHS512
  , jwkRS512
  , jwkES256
  , jwkES512
  )
where

import           Web.Libjwt                     ( Alg(..)
                                                , EcKeyPair(..)
                                                , RsaKeyPair(..)
                                                )

import qualified Crypto.JOSE.JWA.JWS           as Jose
import           Crypto.JOSE.JWK                ( JWK )
import qualified Crypto.JOSE.JWK               as JWK
import           Crypto.JOSE.Types              ( Base64Integer(..) )

import           Data.Aeson                     ( decode )

import           Data.ByteString                ( ByteString )
import qualified Data.ByteString.Char8         as C8

import           Data.Maybe                     ( fromJust )

hs512 :: Alg
hs512 =
  HS512
    "MjZkMDY2OWFiZmRjYTk5YjczZWFiZjYzMmRjMzU5NDYyMjMxODBjMTg3ZmY5OTZjM2NhM2NhN2Mx\
    \YzFiNDNlYjc4NTE1MjQxZGI0OWM1ZWI2ZDUyZmMzZDlhMmFiNjc5OWJlZTUxNjE2ZDRlYTNkYjU5\
    \Y2IwMDZhYWY1MjY1OTQgIC0K"

rsa2048KeyPair :: RsaKeyPair
rsa2048KeyPair =
  let private = C8.pack $ unlines
        [ "-----BEGIN RSA PRIVATE KEY-----"
        , "MIIEpgIBAAKCAQEAwCXp2P+qboao0tjUyU+D3YI+sgBn8dkGaxOvPFLBFQMNkhbL"
        , "0HEoRKNnQCubZNc0jXnMK5hCeGRnDS7lYclROXocRWUn5s2W3jP5xn7lM4otIpuE"
        , "3FStthMCrPSEQiBCXE4cyKiHaZqmbqXlHAHVEuGMM7oddiB6s3zjwf2h1v0SEiHf"
        , "5ZFzTVarStablqh6wVDAiYyM+8aUM0x9p3JcaWW+eDk/UU3jCfCke7R3t2rbD1ZC"
        , "j1cO08Uir3Lhf65TfU+iIrgLU3umV4B3gRcpd8iz0ZTLaG8Qnm0GsPQjR3PTZYEC"
        , "xEnFaRgXcQLHYYMAW9YaX6T3rlTGZAaP5YboxQIDAQABAoIBAQCg/OMBsauc8Ovv"
        , "xEX76MglxeM7hgWQ5vFus05lrzwgm686EClxme1QHMv8QszuXzSjuEFs4SQH9K82"
        , "p2z+UgrgqkOXjNoykVvvDgMe4OCuHv4T+dMGO1hTrXfXawKI2Lhg1/1bzX+u5ii9"
        , "mfbsUUixihHKoQvgFfRX/7JfrV50XZ3diwzd8DoEaIgeAIdyhLhVuh2W7wXbOF+l"
        , "aZW7gqCVzTBhC04E/D6eqFqvnkQyHzZPgaaDi4oL7gP8nGpcswlqKSLO5eVkkEHY"
        , "C88nAwU4Q/+qcAf09ijmTLlo07xLrLC0cOf2yQTwLj6ZffzTJ7NSMaPrTdEXThsW"
        , "wAeB/GcBAoGBAOzLST9/zakFGBTkwiLqgNVgEBUoYjB0Z+Fpx4qBLzKZNQP1yNup"
        , "LhC/4pIVQM+ZjOS0Wx7Sh0FTLHFb018quPiAPsKMEC2CW5v7vKwC4zW72/v5UrIw"
        , "pcBzl67nsc53r5Lblol9PU4oCjDzuFMjMbg+EzD3kVp/gxC9bRMwK3zBAoGBAM+7"
        , "nOV80uteB1ZXazccj6g0ANd2AyJY6gHfxD1CopvRReYm36wmG00HQ3jHZPUcsLQp"
        , "dWvWplRFprZlce0jl7HcB/8g5wUkErMop3KK5cA886HxsATNSl6rYghZGALqxm/a"
        , "+v2AKoZThns8QRYL5bsBD4kTQLEIwp7j6sNbBrkFAoGBAL6fL8o0gkUsWqSHO1mM"
        , "WkZrXMcLiW/kZbPqyb3QHUSoXStg818RpInLTwO2pEP7IpcCMdBwPn3yDPb8qv4T"
        , "kHBMHTnUMznPlRvO3aXDdVFOd9sybMYRr31sEJG250aExwx8RYVNEssWJI4fxST4"
        , "UhA1uJFU2uh1efdB5srpnjiBAoGBALTDCPAZAmCVXcUgJMe8LrWrKuBSbL/Cpz4i"
        , "PV0hUuZL4Is5YIEoV7FblLbQq2UvJgRf3zGLgwjp4vvsooo74pB+auby9pReo3cK"
        , "9UqS2wHBCC/vY7+J9CEU+SVSgbZoHWzQHH/iux5QKEGsWOaaS7nCXoZlHnHusYwZ"
        , "v/tmhh8RAoGBAIi3Lbup0AVwougANLXwMLCfT8HxI8Hozdr+Pe0ibTnjfY+BPuy1"
        , "vSgozXao68TwW3u58PcdvfBnfg/7XCK6TXtij48JDu6qw0IiSRxOZ5Ed/GW2P031"
        , "7TfwnjBohjM2O6NRne8qe6Qv5xLagoVKQfa1WhQEFU2bTNLYA/2kv266"
        , "-----END RSA PRIVATE KEY-----"
        ]
      public = C8.pack $ unlines
        [ "-----BEGIN PUBLIC KEY-----"
        , "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwCXp2P+qboao0tjUyU+D"
        , "3YI+sgBn8dkGaxOvPFLBFQMNkhbL0HEoRKNnQCubZNc0jXnMK5hCeGRnDS7lYclR"
        , "OXocRWUn5s2W3jP5xn7lM4otIpuE3FStthMCrPSEQiBCXE4cyKiHaZqmbqXlHAHV"
        , "EuGMM7oddiB6s3zjwf2h1v0SEiHf5ZFzTVarStablqh6wVDAiYyM+8aUM0x9p3Jc"
        , "aWW+eDk/UU3jCfCke7R3t2rbD1ZCj1cO08Uir3Lhf65TfU+iIrgLU3umV4B3gRcp"
        , "d8iz0ZTLaG8Qnm0GsPQjR3PTZYECxEnFaRgXcQLHYYMAW9YaX6T3rlTGZAaP5Ybo"
        , "xQIDAQAB"
        , "-----END PUBLIC KEY-----"
        ]
  in  FromRsaPem { privKey = private, pubKey = public }

rs256 :: Alg
rs256 = RS256 rsa2048KeyPair

rs512 :: Alg
rs512 = RS512 rsa2048KeyPair

ecP256KeyPair :: EcKeyPair
ecP256KeyPair =
  let private = C8.pack $ unlines
        [ "-----BEGIN EC PRIVATE KEY-----"
        , "MHcCAQEEINQ0e0KOa3EZSB5RTd2xBuO3O7NNFietDIWl+B+R38LuoAoGCCqGSM49"
        , "AwEHoUQDQgAEKZL0X84AvdnGZdsIdAS60OnvF3FNlsrCnaXRoJUVdOYZldzb4po2"
        , "uDXF5W58DS8C31fV+z+0lTG5RvuAqfkdbA=="
        , "-----END EC PRIVATE KEY-----"
        ]
      public = C8.pack $ unlines
        [ "-----BEGIN PUBLIC KEY-----"
        , "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKZL0X84AvdnGZdsIdAS60OnvF3FN"
        , "lsrCnaXRoJUVdOYZldzb4po2uDXF5W58DS8C31fV+z+0lTG5RvuAqfkdbA=="
        , "-----END PUBLIC KEY-----"
        ]
  in  FromEcPem { ecPrivKey = private, ecPubKey = public }

es256 :: Alg
es256 = ES256 ecP256KeyPair

ecP521KeyPair :: EcKeyPair
ecP521KeyPair =
  let private = C8.pack $ unlines
        [ "-----BEGIN EC PRIVATE KEY-----"
        , "MIHcAgEBBEIAIWLn8LIw+NC3gZJIFemY/Ku5QNNncVjNZiQdICh7KzgHPrjCrdQk"
        , "2HNAZ+7r5biSu07Kucvn7OLbubL8iFykX8GgBwYFK4EEACOhgYkDgYYABAGgIDu0"
        , "FLPpH0NNAzlqrRW3IClcxSZt043iTdwLTmbMj51epCDDPb04jfdDWg58pQqXRKEI"
        , "xRUJbv/6aJimWkfkvwBsHhdkIdXSTID9wKTaCSkeGAqGdzjkBdTMA8sfEujYDtHt"
        , "FoCrBx31I4jnh2yX1WNa9oycus38E6IzWeTdq547aA=="
        , "-----END EC PRIVATE KEY-----"
        ]
      public = C8.pack $ unlines
        [ "-----BEGIN PUBLIC KEY-----"
        , "MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBoCA7tBSz6R9DTQM5aq0VtyApXMUm"
        , "bdON4k3cC05mzI+dXqQgwz29OI33Q1oOfKUKl0ShCMUVCW7/+miYplpH5L8AbB4X"
        , "ZCHV0kyA/cCk2gkpHhgKhnc45AXUzAPLHxLo2A7R7RaAqwcd9SOI54dsl9VjWvaM"
        , "nLrN/BOiM1nk3aueO2g="
        , "-----END PUBLIC KEY-----"
        ]
  in  FromEcPem { ecPrivKey = private, ecPubKey = public }

es512 :: Alg
es512 = ES512 ecP521KeyPair

jwkHS512 :: (Jose.Alg, JWK)
jwkHS512 =
  ( Jose.HS512
  , JWK.fromOctets
    ("MjZkMDY2OWFiZmRjYTk5YjczZWFiZjYzMmRjMzU5NDYyMjMxODBjMTg3ZmY5OTZjM2NhM2NhN2Mx\
    \YzFiNDNlYjc4NTE1MjQxZGI0OWM1ZWI2ZDUyZmMzZDlhMmFiNjc5OWJlZTUxNjE2ZDRlYTNkYjU5\
    \Y2IwMDZhYWY1MjY1OTQgIC0K" :: ByteString
    )
  )

jwkRS512 :: (Jose.Alg, JWK)
jwkRS512 =
  let
    rsaN =
      Base64Integer
        21071666595382654004815830003291135226213375605579463114213666885162970050362260641378848210839698813616018661779188948656905472806115096313509733841002972548378762928254795013919788232987376549887236239308783399460589276366127380239651445012871883061369461005966640738975889383298437567168811300366234946027700641546838113190525302696713965296806901671241628461497496694989297235831876004199661653018743316900741288781592524963173982960567805012775229890256541370866292114269655407207451318367259794670451071683128223951472325608349088189586629857137365222371124466180904001530025257089565415545120432511743113512473
    rsaE = Base64Integer 65537
    rsaD =
      Base64Integer
        19950515163090981903334334066316965085166241303785734565771366254548763166226380102805400483430784310921677189425800300046706205465911496196854890898793573807572855634194577576235147471762007948494789335018539297443117088034517966093510111281393721774844363572031525059942535304235287715989818593889327836199410763613773297881984598831126309157462916917948945881897383450666311618062870578744825198060209947343612529835724282995784470652634835141123292719604629163927545705270795831312767908907697441504682913850869791489990390358315243559993131306656391164462063211130191489451712836337004003290172594730408707046473
    rsaP =
      Base64Integer
        153349769578169153058871716836180422106339541427708058036596622771192505561541419690995294407950382598829412251529799333727105395997138736446264960660733442117439252140820758012973354169242686630895924852681492970479214660745044040197294406602779131107543820213877788006961751859321067912409389608332161173411
    rsaQ =
      Base64Integer
        137409183289587497714220607669486353304153007305941898031265596693236647869265299751218993497626466629738881077301044167807443992262379561682756469245629338638948544863207793485455072238568804673037755612969639524433881085993953622535671527176972751290168290320944672117795106277492834923153567627878390957843
    rsaDp =
      Base64Integer
        153300631760430447408411117387722912777804009890256208406330230823465343155316045172578050695504482450293845813376052201786243452159063452050192946925379742645622320876115976959243820616630359297950431247208152546712791670558193163214152926484088035058697238584805791523324322669870135730189260563948454635353
    rsaDq =
      Base64Integer
        32368325855999691620186119920068515835474832946108778580140657670479078532824476212815948572811654360588810077839594730650034642302006739296250886861071238077850491105760134211643123811267302539670062272502941773016925648192237301443546348422388960959726842332953047105520863797731577361546069808492707929981
    rsaQi =
      Base64Integer
        27571505766428475328455285089562516511258707017324580945158490959713515982603670667108107072333234933006284329274187908422010559614331442880924878733162609474802580561043028467939476205597975399753477385845907675851008053322874093082221184241483472466527639166322448897870481530431990331215794498080587118813
  in
    ( Jose.RS512
    , JWK.fromKeyMaterial
    $ JWK.RSAKeyMaterial
    $ JWK.RSAKeyParameters rsaN rsaE
    $ Just
    $ JWK.RSAPrivateKeyParameters rsaD
    $ Just
    $ JWK.RSAPrivateKeyOptionalParameters rsaP rsaQ rsaDp rsaDq rsaQi Nothing
    )


jwkES256 :: (Jose.Alg, JWK)
jwkES256 =
  ( Jose.ES256
  , JWK.fromKeyMaterial
    $ fromJust
    $ decode
        "{\"crv\":\"P-256\",\"d\":\"2cnW8FRZ_fS_K_MWQ6SaFR45EXXMPvglEkHcb2rCqqw\",\"x\":\"I0EbOl87INBId_qblVunGENMHERnsXP39DV6wfJAvx8\",\"kty\":\"EC\",\"y\":\"on_b2TDmYusX6cOc07BoAfelzdKdMRHB7R8gwRCFhkA\"}"
  )

jwkES512 :: (Jose.Alg, JWK)
jwkES512 =
  ( Jose.ES512
  , JWK.fromKeyMaterial
    $ fromJust
    $ decode
        "{\"crv\":\"P-521\",\"d\":\"AD1kHuRIRTWjb0YKg9HDINWjLH_TprOmAGis5puv2tPaOZ7666JNkebxMR0CG8kz8LezWPJA069otTMDtlQZrkCL\",\"x\":\"APrcS4DmgcxjPCVUBPOE-T2iO4eWt4GFNFODHDQVY_WMF3WPsFHvmtBaTdbCYEltzEacgBSD1e0fxnHM9mihMAzC\",\"kty\":\"EC\",\"y\":\"ARSXmiJY-ed-3MMWw6F5WfYyw1gZ_hGY0Egqn2YZEKE62kgTYBF6GJ8I4V-Ix1_DciwCGUSbXe1OUIPDDBcRx4Hk\"}"
  )