filepath-crypto- Reversable and secure encoding of object ids as filepaths

Safe HaskellNone




Given a value of a serializable type (like Int) we perform serialization and compute a cryptographic hash of the associated namespace (carried as a phantom type of kind Symbol). The serialized payload is encrypted using a symmetric cipher in CBC mode using the hashed namespace as an initialization vector (IV).

The ciphertext is then base32-encoded and padding stripped.

Rather than being indicated by the amount of padding, the length of the serialized plaintext is instead carried at the type level within CryptoFileName (analogously to the namespace). Mismatches in serialized plaintext length are checked for but are not guaranteed to cause runtime errors in all cases.

Since the serialized payload is padded to the length of the next cipher block we can detect namespace mismatches by checking that all bytes expected to have been inserted during padding are nil. The probability of detecting a namespace mismatch is thus \(1 - 2^{b \left \lceil \frac{l}{b} \right \rceil - l}\) where \(l\) is the length of the serialized payload and \(b\) the length of a ciphertext block (both in bits).



type CryptoFileName (namespace :: Symbol) = CryptoID namespace (CI FilePath) Source #

type HasCryptoFileName (namespace :: Symbol) = HasCryptoID namespace (CI FilePath) Source #

encrypt :: forall a m namespace. (KnownSymbol namespace, Binary a, MonadThrow m, HasFixedSerializationLength a) => CryptoIDKey -> a -> m (CryptoFileName namespace) Source #

Encrypt an arbitrary serializable value

We only expect to fail if the given value is not serialized in such a fashion that it meets the expected length given at type level.

decrypt :: forall a m namespace. (KnownSymbol namespace, Binary a, MonadThrow m, HasFixedSerializationLength a) => CryptoIDKey -> CryptoFileName namespace -> m a Source #

Decrypt an arbitrary serializable value

Since no integrity guarantees can be made (we do not sign the values we encrypt) it is likely that deserialization will fail emitting DeserializationError or InvalidNamespaceDetected.

Orphan instances

(MonadCrypto m, (~) * (MonadCryptoKey m) CryptoIDKey, KnownSymbol namespace, Binary a, HasFixedSerializationLength a) => HasCryptoID namespace (CI FilePath) a m Source # 


encrypt :: a -> m (CryptoID namespace (CI FilePath)) #

decrypt :: CryptoID namespace (CI FilePath) -> m a #