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