web-push-0.1.2.0: test/WebPushEncryptionSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module WebPushEncryptionSpec where
import Web.WebPush.Internal
import Test.Hspec
import qualified Data.Binary as Binary
import qualified Data.ByteString.Base64.URL as B64.URL
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LB
-- Test to match input and output from the specification.
-- https://tools.ietf.org/html/draft-ietf-webpush-encryption-04
spec :: Spec
spec = describe "Web Push Encryption Test" $ do
let encryptionInput = EncryptionInput
{ applicationServerPrivateKey = bytes32Int $ bsTo32Bytes $ BS.concat [ "nCScek-QpEjmOOlT-rQ38nZ"
, "zvdPlqa00Zy0i6m2OJvY"
]
, userAgentPublicKeyBytes = B64.URL.decodeLenient $ BS.concat [ "BCEkBjzL8Z3C-oi2Q7oE5t2Np-"
, "p7osjGLg93qUP0wvqR"
, "T21EEWyf0cQDQcakQMqz4hQKYOQ3il2nNZct4HgAUQU"
]
, authenticationSecret = B64.URL.decodeLenient "R29vIGdvbyBnJyBqb29iIQ"
, salt = B64.URL.decodeLenient "lngarbyKfMoi9Z75xYXmkg"
, plainText = "I am the walrus"
, paddingLength = 0
}
encryptionOutput = webPushEncrypt encryptionInput
expectedEncryptionOutput = EncryptionOutput
{ sharedECDHSecretBytes = B64.URL.decodeLenient $ BS.concat [ "RNjC-"
-- NOTE: the specs example might have printed this wrong
-- there should be two consecutive hyphens and not one
-- near the end of the encoded string, just before "NOQ6Y"
, "NVW4BGJbxWPW7G2mowsLeDa53LYKYm4--NOQ6Y"
]
, inputKeyingMaterialBytes = B64.URL.decodeLenient $ BS.concat [ "EhpZec37Ptm4IRD5-jtZ0q6r1iK5vYmY1tZwtN8"
, "fbZY"
]
, contentEncryptionKeyContext = B64.URL.decodeLenient $ BS.concat [ "Q29udGVudC1FbmNvZGluZzogYWVzZ2NtAFAtMjU2AABB BCEkBjzL8Z3C-"
, "oi2Q7oE5t2Np-p7osjGLg93qUP0wvqR"
, "T21EEWyf0cQDQcakQMqz4hQKYOQ3il2nNZct4HgAUQUA"
, "QQTaEQ22_OCRpvIOWeQhcbq0qrF1iddSLX1xFmFSxPOW"
, "OwmJA417CBHOGqsWGkNRvAapFwiegz6Q61rXVo_5roB1"
]
, contentEncryptionKey = B64.URL.decodeLenient "AN2-xhvFWeYh5z0fcDu0Ww"
, nonceContext = B64.URL.decodeLenient $ BS.concat [ "Q29udGVudC1FbmNvZGluZzogbm9uY2UAUC0yNT"
, "YAAEEE ISQGPMvxncL6iLZDugTm3Y2n6nuiyMYuD3epQ_TC-pFP"
, "bUQRbJ_RxANBxqRAyrPiFApg5DeKXac1ly3geABRBQBB"
, "BNoRDbb84JGm8g5Z5CFxurSqsXWJ11ItfXEWYVLE85Y7"
, "CYkDjXsIEc4aqxYaQ1G8BqkXCJ6DPpDrWtdWj_mugHU"
]
, nonce = B64.URL.decodeLenient "JY1Okw5rw1Drkg9J"
, paddedPlainText = B64.URL.decodeLenient "AABJIGFtIHRoZSB3YWxydXM"
, encryptedMessage = B64.URL.decodeLenient $ BS.concat [ "6nqAQUME8hNqw5J3kl8cpVVJylXKYqZOeseZG8UueKpA" ]
}
it "should match the shared secret" $ do
(sharedECDHSecretBytes <$> encryptionOutput) `shouldBe` Right (sharedECDHSecretBytes expectedEncryptionOutput)
it "should match the input keying material" $ do
(inputKeyingMaterialBytes <$> encryptionOutput) `shouldBe` Right (inputKeyingMaterialBytes expectedEncryptionOutput)
it "should match the context for content encryption key derivation" $ do
(contentEncryptionKeyContext <$> encryptionOutput) `shouldBe` Right (contentEncryptionKeyContext expectedEncryptionOutput)
it "should match the content encryption key" $ do
(contentEncryptionKey <$> encryptionOutput) `shouldBe` Right (contentEncryptionKey expectedEncryptionOutput)
it "should match the context for nonce derivation" $ do
(nonceContext <$> encryptionOutput) `shouldBe` Right (nonceContext expectedEncryptionOutput)
it "should match the nonce" $ do
(nonce <$> encryptionOutput) `shouldBe` Right (nonce expectedEncryptionOutput)
it "should match the paddded plain text" $ do
(paddedPlainText <$> encryptionOutput) `shouldBe` Right (paddedPlainText expectedEncryptionOutput)
it "should match the encrypted message" $ do
(encryptedMessage <$> encryptionOutput) `shouldBe` Right (encryptedMessage expectedEncryptionOutput)
where
bsTo32Bytes :: ByteString -> Bytes32
bsTo32Bytes = Binary.decode . LB.fromStrict . B64.URL.decodeLenient