Copyright | (c) Piyush P Kurur 2016 |
---|---|
License | Apache-2.0 OR BSD-3-Clause |
Maintainer | Piyush P Kurur <ppk@iitpkd.ac.in> |
Stability | experimental |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
Synopsis
- lock :: Encodable plain => Key Cipher -> plain -> IO Locked
- unlock :: Encodable plain => Key Cipher -> Locked -> Maybe plain
- lockWith :: (Encodable plain, Encodable aad) => aad -> Key Cipher -> plain -> IO Locked
- unlockWith :: (Encodable plain, Encodable aad) => aad -> Key Cipher -> Locked -> Maybe plain
- type Locked = AEAD Cipher AuthTag
- type Cipher = Prim
Authenticated encryption
Suppose that Alice wants to send a private message to Bob that
should not be seen by anyone else. Alice can use their shared
secret key K
to encrypt the message, which Bob decrypts when he
receives it. The secrecy of the key K
ensures that a third party
Eve will not be able to read what Alice sends. However, it is
possible for Eve to forge message and pretend that it has
originated from Alice. Consider a string R
that Bob receives
purportedly from Alice. Since stream ciphers encrypt message M
by
xoring it with the keystream KS
generated using the key K
, from
Bob's point of view it is impossible to know whether it was some
nonsense that Eve sent or whether it was from Alice who wanted to
actually send the message R ⊕ KS
. In many situations, Eve can
exploit this ability to fake communication and breach the security
of the protocol. Authenticated encryption is to solve this issue.
Authenticated encryption via message locking
To send a message m
using a key k
, Alice computes the locked
variant using the function lock
. At Bobs end, he can unlock this
locked message using the function unlock
. If there has been any
tampering of message on the way from A to B, the unlocking will
fail. It is computationally infeasible to decrypt or fake the
authentication without knowing the key. Sometimes the protocol
requires additional authenticated data. The lockWith
and the
unlockWith
variants are used for this purpose.
Safety against key reuse
The interface exposed here is safe even with key reuse. Under the
hood, both lock
and lockWith
uses randomly generated nounce for
each invocation (hence the result is an IO
type). The nounce is
large (192-bits) and is generated using cryptographically secure
pseudo-random generator (csprg). Thus even when a particular key is
used multiple times, each such invocation is paired with a distinct
nounce thereby preventing the reuse of the (key, nounce)-pair.
Serialisation
Unfortunately, there does not seem to be an agreed upon format for
serialising AEAD tokens. As a result the Locked type does not have
an instance of Encodable
unlike the message digest and message
authentication type. However, for particular wire protocol, one can
take apart the AEAD token using the Raaz.AuthEncrypt.Unsafe
interface and individually serialise the constituents.
Security assumption
The security of the interface is compromised if and only if the key gets exposed. Otherwise an adversary should not be able to read, tamper or forge Locked data.
Generate a locked version of an unencrypted object. You will need
the exact same key to unlock
the object. Unlike unsafelock
,
this function does not require a nounce as internally a random
nounce is generated and used each time. Because of this, it is safe
to use the same key multiple times.
Unlock the locked version of an object. You will need the exact same key that was used to lock the object.
Locking with additional data
Some protocols have additional data that needs to be factored in
when sending the locked packet. In such situations one can use the
lockWith
and unlockWith
variants.
:: (Encodable plain, Encodable aad) | |
=> aad | the authenticated additional data. |
-> Key Cipher | The key |
-> plain | the unencrypted object |
-> IO Locked |
This function locks a plain text message together with and
additional authenticated data to produce an AEAD token. A peer
who has the right key
and the additional authenticated data can
recover the unencrypted object using the unlockWith
function.
Unlike unsafeLockWith
, this function does not require a nounce as
internally a random nounce is generated and used each time. As a
result we do not put any restriction on the key used; it is safe
to use the same key multiple times.
:: (Encodable plain, Encodable aad) | |
=> aad | the authenticated additional data. |
-> Key Cipher | The key for the stream cipher |
-> Locked | The message to unlock |
-> Maybe plain |
Unlock an encrypted authenticated version of the data given the
additional data, key, and nounce. An attempt to unlock the element
can result in Nothing
if either of the following is true.
- The key/nounce used to encrypt the data is different
- The Authenticated additional data (
aad
) is incorrect - The cipher text is of the wrong type and hence the
fromByteString
failed - The Locked message has been tampered with by the adversary
The interface provided does not indicate which of the above failures had happened. This is a deliberate design as revealing the nature of the failure can leak information to a potential attacker.