aviary-ps/src/Main.purs

72 lines
2.3 KiB
Plaintext

module Main where
import Prelude
import Effect (Effect)
import Effect.Aff (Aff, launchAff)
import Effect.Class (liftEffect)
import Effect.Console (log)
import Fetch (fetch)
import Data.Base64 (decodeBase64, fromString)
import Data.Either (Either, note)
import Data.Maybe (Maybe(..))
import Data.ArrayBuffer.Builder (execPut, putInt32be)
import Data.ArrayBuffer.Types (ArrayBuffer)
import Data.Foldable (traverse_)
import Data.String (drop, indexOf', indexOf, splitAt)
import Data.String.Pattern (Pattern(..))
import Crypto.Subtle.Constants.AES (aesGCM, t128)
import Crypto.Subtle.Encrypt (aesGCM, decrypt) as Alg
import Crypto.Subtle.Key.Import (aes)
import Crypto.Subtle.Key.Import (importKey) as SC
import Crypto.Subtle.Key.Types (CryptoKey, decrypt, raw)
nonceE :: Effect ArrayBuffer
nonceE = execPut $ traverse_ putInt32be [0xd0, 0xc3, 0x75, 0x56, 0x58, 0xc1, 0x7e, 0x5f, 0xd6, 0xcc, 0xb6, 0x76]
data AviaryError
= MalformedKey
| MalformedUrl
| DecryptFailed
instance showAviaryError :: Show AviaryError where
show MalformedKey = "Malformed key!!"
show MalformedUrl = "Malformed url!!"
show DecryptFailed = "Either the data provided by the server was bad, or valid but incorrect key. Expiration likely."
type UrlInfo =
{ server :: String
, fileId :: String
, key :: String
}
parseUrl :: String -> Either AviaryError UrlInfo
parseUrl url = note MalformedUrl do
slashIndex <- indexOf' (Pattern "/") 8 url
let { after, before: server } = splitAt (1 + slashIndex) url
poundIndex <- indexOf (Pattern "#") after
let { after: key, before: fileId } = splitAt poundIndex after
Just { server, fileId, key: drop 1 key }
decodeKey :: String -> Either AviaryError ArrayBuffer
decodeKey key = note MalformedKey $ decodeBase64 <$> fromString key
importKey :: ArrayBuffer -> Aff CryptoKey
importKey key =
SC.importKey raw key (aes aesGCM) false [decrypt]
decryptBlob :: CryptoKey -> ArrayBuffer -> ArrayBuffer -> Aff ArrayBuffer
decryptBlob key cyphertext nonce =
-- nonce <- makeAff (\_ -> nonceE)
Alg.decrypt (Alg.aesGCM nonce Nothing (Just t128)) key cyphertext
main_aff :: Aff Unit
main_aff = do
{ status, text } <- fetch "https://envs.sh/Q_V.txt" {}
responseText <- text
liftEffect $ log responseText
main :: Effect Unit
main = launchAff main_aff $> unit