Skip to content

Commit

Permalink
finished encryption and decryption with @hivemind-js
Browse files Browse the repository at this point in the history
  • Loading branch information
maxpschonder committed Feb 2, 2021
1 parent a1edfe1 commit c74f157
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 39 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ node_modules
# Generated files
.psci
output

/.spago
/.idea
/.psc-ide-port
3 changes: 1 addition & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 10 additions & 1 deletion spago.dhall
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,16 @@ Welcome to a Spago project!
You can edit this file as you like.
-}
{ name = "my-project"
, dependencies = [ "aff-promise", "console", "effect", "psci-support" ]
, dependencies =
[ "aff-promise"
, "console"
, "debug"
, "effect"
, "node-buffer"
, "psci-support"
, "spec"
, "spec-discovery"
]
, packages = ./packages.dhall
, sources = [ "src/**/*.purs", "test/**/*.purs" ]
}
12 changes: 8 additions & 4 deletions src/AWS/Crypto/Crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

const crypto = require("@aws-crypto/client-node")

exports.makeClient = () => crypto.buildClient(
crypto.CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
)

exports.makeKeyringImpl = (generatorKeyId, keyIds) => () => new crypto.KmsKeyringNode({ generatorKeyId, keyIds })

exports.encryptImpl = (keyring, cleartext, context) => () => crypto.encrypt(keyring, cleartext, {
encryptionContext: context,
})
exports.encryptImpl = (client, keyring, context, plaintext) => () => client.encrypt(keyring, plaintext, {
encryptionContext: context,
})

exports.decryptImpl = (keyring, ciphertext) => decrypt(keyring, result)
exports.decryptImpl = (client, keyring, ciphertext) => () => client.decrypt(keyring, ciphertext)
52 changes: 34 additions & 18 deletions src/AWS/Crypto/Crypto.purs
Original file line number Diff line number Diff line change
@@ -1,42 +1,58 @@
module AWS.Crypto.Crypto where

import Prelude

import Control.Promise (Promise, toAffE)
import Data.Function.Uncurried (Fn2, Fn3, runFn2, runFn3)
import Data.Function.Uncurried (Fn2, Fn3, Fn4, runFn2, runFn3, runFn4)
import Data.Newtype (class Newtype, un)
import Effect (Effect)
import Effect.Aff (Aff)
import Effect.Class (liftEffect)
import Node.Buffer (Buffer, toString, fromString)
import Node.Encoding (Encoding(..))

foreign import data KmsKeyring :: Type

foreign import data KmsKeyring :: Type
newtype Arn
= Arn String

newtype Arn = Arn String
derive instance ntArn :: Newtype Arn _

foreign import data Client :: Type

foreign import makeClient :: Effect Client

foreign import makeKeyringImpl :: Fn2 String (Array String) (Effect KmsKeyring)

makeKeyring :: Arn -> Array Arn -> Effect KmsKeyring
makeKeyring (Arn generatorKeyId) keyIds = runFn2 makeKeyringImpl generatorKeyId $ map (un Arn) keyIds

makeKeyring (Arn generatorKeyId) keyIds = runFn2 makeKeyringImpl generatorKeyId $ map (un Arn) keyIds

type InternalEncryptionResult = { result :: String }
type InternalEncryptionResult
= { result :: Buffer }

foreign import encryptImpl :: forall a. Fn3 KmsKeyring String a (Effect (Promise InternalEncryptionResult))
foreign import encryptImpl :: forall a. Fn4 Client KmsKeyring a String (Effect (Promise InternalEncryptionResult))

type EncryptionResult = { ciphertext :: String }
type EncryptionResult
= { ciphertext :: String }

encrypt :: forall a. KmsKeyring -> String -> a -> Aff EncryptionResult
encrypt keyring plaintext context = runFn3 encryptImpl keyring plaintext context # toAffE <#>
\ir -> { ciphertext : ir.result }
encrypt :: forall a. Client -> KmsKeyring -> a -> String -> Aff EncryptionResult
encrypt client keyring context plaintext = runFn4 encryptImpl client keyring context plaintext # toAffE >>= convert
where
convert :: InternalEncryptionResult -> Aff EncryptionResult
convert ir = liftEffect $ toString Base64 ir.result <#> { ciphertext: _ }

type InternalDecryptionResult a
= { plaintext :: Buffer, messageHeader :: { encryptionContext :: a } }

type InternalDecryptionResult a = { plaintext :: String, messageHeader :: { encryptionContext :: a } }
foreign import decryptImpl :: forall a. Fn3 Client KmsKeyring Buffer (Effect (Promise (InternalDecryptionResult a)))

foreign import decryptImpl :: forall a. Fn2 KmsKeyring String (Effect (Promise (InternalDecryptionResult a)))
type DecryptionResult a
= { plaintext :: String, encryptionContext :: a }

type DecryptionResult a = { plaintext :: String, encryptionContext :: a }
decrypt :: forall a. Client -> KmsKeyring -> String -> Aff (DecryptionResult a)
decrypt client keyring ciphertext = (convertIn >>= runFn3 decryptImpl client keyring) # toAffE >>= convertOut
where
convertIn :: Effect Buffer
convertIn = fromString ciphertext Base64

decrypt :: forall a. KmsKeyring -> String -> Aff (DecryptionResult a)
decrypt keyring ciphertext = runFn2 decryptImpl keyring ciphertext # toAffE <#>
\ir -> { plaintext : ir.plaintext, encryptionContext : ir.messageHeader.encryptionContext }
convertOut :: InternalDecryptionResult a -> Aff (DecryptionResult a)
convertOut ir = liftEffect $ toString UTF8 ir.plaintext <#> { plaintext: _, encryptionContext: ir.messageHeader.encryptionContext }
10 changes: 0 additions & 10 deletions src/Main.purs

This file was deleted.

24 changes: 24 additions & 0 deletions test/AWS/Crypto/CryptoSpec.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module AWS.Crypto.CryptoSpec where

import AWS.Crypto.Crypto (Arn(..), EncryptionResult, decrypt, encrypt, makeClient, makeKeyring)
import Effect.Class (liftEffect)
import Prelude (Unit, bind, ($))
import Test.Spec (Spec, describe, pending')
import Test.Spec.Assertions (shouldEqual)

spec :: Spec Unit
spec =
describe "AWS.Crypto" do
describe "decrypt/encrypt" do
pending' "should roundtrip encrypt/decrypt data" do
client <- liftEffect makeClient
keyring <-
liftEffect
$ makeKeyring
(Arn "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f")
[]
let
testData = "some-data"
encrypted :: EncryptionResult <- encrypt client keyring {} testData
decrypted <- decrypt client keyring (encrypted.ciphertext)
decrypted.plaintext `shouldEqual` testData
11 changes: 7 additions & 4 deletions test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ module Test.Main where
import Prelude

import Effect (Effect)
import Effect.Class.Console (log)
import Effect.Aff (launchAff_)
import Test.Spec.Discovery (discover)
import Test.Spec.Reporter.Console (consoleReporter)
import Test.Spec.Runner (runSpec)

main :: Effect Unit
main = do
log "🍝"
log "You should add some tests."
main = launchAff_ do
specs <- discover "\\..*Spec"
runSpec [consoleReporter] specs

0 comments on commit c74f157

Please sign in to comment.