packages feed

rncryptor-0.3.0.2: test/PasswordBasedVectors.hs

{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module PasswordBasedVectors where

import           Crypto.MAC.HMAC (update)
import           Crypto.RNCryptor.Types
import           Crypto.RNCryptor.V3.Encrypt
import           Data.ByteString as B
import           Data.ByteString.Base16
import           Data.Monoid
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified System.IO.Streams.ByteString as S
import qualified System.IO.Streams.List as S
import           Test.Tasty.HUnit

--------------------------------------------------------------------------------
data TestVector = TestVector {
   password :: !Password
 , enc_salt_hex :: !EncryptionSalt
 , hmac_salt_hex :: !HMACSalt
 , iv_hex :: !IV
 , plaintext_hex :: !ByteString
 , ciphertext_hex :: !ByteString
 }

--------------------------------------------------------------------------------
unhex :: ByteString -> ByteString
unhex = decodeLenient

--------------------------------------------------------------------------------
withTestVector :: TestVector -> Assertion
withTestVector TestVector{..} = do
  let header = newRNCryptorHeaderFrom (unhex enc_salt_hex) (unhex hmac_salt_hex) (unhex iv_hex)
  let ctx = newRNCryptorContext password header
  encrypt ctx (unhex plaintext_hex) @?= (unhex ciphertext_hex)
  -- Test the streaming API
  inS <- S.fromByteString (unhex plaintext_hex)
  (outS, flush) <- S.listOutputStream
  let ctx' = ctx { ctxHMACCtx = update (ctxHMACCtx ctx) (renderRNCryptorHeader header) }
  encryptStreamWithContext ctx' inS outS
  result <- flush
  (B.unpack $ B.concat result) @?= (B.unpack $ unhex ciphertext_hex)

--------------------------------------------------------------------------------
allEmptyOrZero :: Assertion
allEmptyOrZero = withTestVector $ TestVector {
   password = "a"
 , enc_salt_hex = "0000000000000000"
 , hmac_salt_hex = "0000000000000000"
 , iv_hex = "00000000000000000000000000000000"
 , plaintext_hex = ""
 , ciphertext_hex = "03010000000000000000000000000000000000000000000000000000000000000000b3039be31cd7ece5e754"
                  <> "f5c8da17003666313ae8a89ddcf8e3cb41fdc130b2329dbe07d6f4d32c34e050c8bd7e933b12"
 }

--------------------------------------------------------------------------------
oneByte :: Assertion
oneByte = withTestVector $ TestVector {
   password = "thepassword"
 , enc_salt_hex = "0001020304050607"
 , hmac_salt_hex = "0102030405060708"
 , iv_hex = "02030405060708090a0b0c0d0e0f0001"
 , plaintext_hex = "01"
 , ciphertext_hex = "03010001020304050607010203040506070802030405060708090a0b0c0d0e0f0001a1f8"
                  <> "730e0bf480eb7b70f690abf21e029514164ad3c474a51b30c7eaa1ca545b7de3de5b010acbad0a9a13857df696a8"
 }

--------------------------------------------------------------------------------
exactlyOneBlock :: Assertion
exactlyOneBlock = withTestVector $ TestVector {
   password = "thepassword"
 , enc_salt_hex = "0102030405060700"
 , hmac_salt_hex = "0203040506070801"
 , iv_hex = "030405060708090a0b0c0d0e0f000102"
 , plaintext_hex = "0123456789abcdef"
 , ciphertext_hex = "030101020304050607000203040506070801030405060708090a0b0c0d0e0f0001020e437"
                  <> "fe809309c03fd53a475131e9a1978b8eaef576f60adb8ce2320849ba32d742900438ba897d22210c76c35c849df"
 }

--------------------------------------------------------------------------------
moreThanOneBlock :: Assertion
moreThanOneBlock = withTestVector $ TestVector {
   password = "thepassword"
 , enc_salt_hex = "0203040506070001"
 , hmac_salt_hex = "0304050607080102"
 , iv_hex = "0405060708090a0b0c0d0e0f00010203"
 , plaintext_hex = "0123456789abcdef01234567"
 , ciphertext_hex = "0301020304050607000103040506070801020405060708090a0b0c0d0e0f00010203e01bbda5df2ca8adace3"
                  <> "8f6c588d291e03f951b78d3417bc2816581dc6b767f1a2e57597512b18e1638f21235fa5928c"
 }

--------------------------------------------------------------------------------
multibytePassword :: Assertion
multibytePassword = withTestVector $ TestVector {
   password = T.encodeUtf8 (T.pack "中文密码")
 , enc_salt_hex = "0304050607000102"
 , hmac_salt_hex = "0405060708010203"
 , iv_hex = "05060708090a0b0c0d0e0f0001020304"
 , plaintext_hex = "23456789abcdef0123456701"
 , ciphertext_hex = "03010304050607000102040506070801020305060708090a0b0c0d0e0f00010203048a9e08bdec1c4bfe13e8"
                  <> "1fb85f009ab3ddb91387e809c4ad86d9e8a6014557716657bd317d4bb6a7644615b3de402341"
 }

--------------------------------------------------------------------------------
longerTextAndPassword :: Assertion
longerTextAndPassword = withTestVector $ TestVector {
   password = "It was the best of times, it was the worst of times; it was the age of wisdom, it was the age of foolishness;"
 , enc_salt_hex = "0405060700010203"
 , hmac_salt_hex = "0506070801020304"
 , iv_hex = "060708090a0b0c0d0e0f000102030405"
 , plaintext_hex = "697420776173207468652065706f6368206f662062656c6965662c20697420776173207468652065706f6368206f6620696e6"
               <> "3726564756c6974793b206974207761732074686520736561736f6e206f66204c696768742c20697420776173207468652073"
               <> "6561736f6e206f66204461726b6e6573733b206974207761732074686520737072696e67206f6620686f70652c20697420776"
               <> "173207468652077696e746572206f6620646573706169723b207765206861642065766572797468696e67206265666f726520"
               <> "75732c20776520686164206e6f7468696e67206265666f72652075733b207765207765726520616c6c20676f696e672064697"
               <> "26563746c7920746f2048656176656e2c207765207765726520616c6c20676f696e6720746865206f74686572207761792e0a0a"
 , ciphertext_hex = "030104050607000102030506070801020304060708090a0b0c0d0e0f000102030405d564c7a99da921a6e7c4078a82641d9"
                 <> "5479551283167a2c81f31ab80c9d7d8beb770111decd3e3d29bbdf7ebbfc5f10ac87e7e55bfb5a7f487bcd39835705e83b9"
                 <> "c049c6d6952be011f8ddb1a14fc0c925738de017e62b1d621ccdb75f2937d0a1a70e44d843b9c61037dee2998b2bbd740b9"
                 <> "10232eea71961168838f6995b9964173b34c0bcd311a2c87e271630928bae301a8f4703ac2ae4699f3c285abf1c55ac324b"
                 <> "073a958ae52ee8c3bd68f919c09eb1cd28142a1996a9e6cbff5f4f4e1dba07d29ff66860db9895a48233140ca249419d630"
                 <> "46448db1b0f4252a6e4edb947fd0071d1e52bc15600622fa548a6773963618150797a8a80e592446df5926d0bfd32b544b7"
                 <> "96f3359567394f77e7b171b2f9bc5f2caf7a0fac0da7d04d6a86744d6e06d02fbe15d0f580a1d5bd16ad91348003611358d"
                 <> "cb4ac9990955f6cbbbfb185941d4b4b71ce7f9ba6efc1270b7808838b6c7b7ef17e8db919b34fac"
 }