tahoe-chk-0.1.0.2: src/Tahoe/CHK/Crypto.hs
module Tahoe.CHK.Crypto (
sha1,
sha256,
sha256d,
storageIndexLength,
taggedHash,
taggedPairHash,
blockHash,
storageIndexHash,
ciphertextTag,
ciphertextSegmentHash,
uriExtensionHash,
convergenceEncryptionTag,
convergenceEncryptionHashLazy,
convergenceSecretLength,
) where
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteArray as BA
import Data.Serialize (
encode,
)
import Crypto.Hash (
Digest,
hash,
hashDigestSize,
hashlazy,
)
import Crypto.Types (ByteLength)
import Crypto.Hash.Algorithms (
SHA1,
SHA256 (SHA256),
)
import Crypto.Cipher.AES128 (
AESKey128,
)
import Tahoe.Netstring (
netstring,
)
import Tahoe.CHK.URIExtension (
URIExtension,
showBytes,
uriExtensionToBytes,
)
import Tahoe.CHK.Types (Parameters (Parameters), StorageIndex)
toBytes :: Digest a -> B.ByteString
toBytes = B.pack . BA.unpack
sha1 :: B.ByteString -> B.ByteString
sha1 xs = toBytes (hash xs :: Digest SHA1)
sha256 :: B.ByteString -> B.ByteString
sha256 xs = toBytes (hash xs :: Digest SHA256)
sha256d :: B.ByteString -> B.ByteString
sha256d = sha256 . sha256
taggedHash :: Int -> B.ByteString -> B.ByteString -> B.ByteString
taggedHash size tag bytes = B.take size . sha256d . B.concat $ [netstring tag, bytes]
taggedPairHash :: Int -> B.ByteString -> B.ByteString -> B.ByteString -> B.ByteString
taggedPairHash size tag left right = B.take size . sha256d . B.concat $ [netstring tag, netstring left, netstring right]
blockTag :: B.ByteString
blockTag = "allmydata_encoded_subshare_v1"
-- allmydata.util.hashutil.block_hash
blockHash :: B.ByteString -> B.ByteString
blockHash = taggedHash (hashDigestSize SHA256) blockTag
storageIndexTag :: B.ByteString
storageIndexTag = "allmydata_immutable_key_to_storage_index_v1"
-- Compute the storage index for a given encryption key
-- allmydata.util.hashutil.storage_index_hash
storageIndexHash :: AESKey128 -> StorageIndex
storageIndexHash = taggedHash storageIndexLength storageIndexTag . encode
ciphertextTag :: B.ByteString
ciphertextTag = "allmydata_crypttext_v1"
ciphertextSegmentTag :: B.ByteString
ciphertextSegmentTag = "allmydata_crypttext_segment_v1"
ciphertextSegmentHash :: B.ByteString -> B.ByteString
ciphertextSegmentHash = taggedHash (hashDigestSize SHA256) ciphertextSegmentTag
uriExtensionTag :: B.ByteString
uriExtensionTag = "allmydata_uri_extension_v1"
uriExtensionHash :: URIExtension -> B.ByteString
uriExtensionHash = taggedHash (hashDigestSize SHA256) uriExtensionTag . uriExtensionToBytes
convergenceEncryptionTagPrefix :: B.ByteString
convergenceEncryptionTagPrefix = "allmydata_immutable_content_to_key_with_added_secret_v1+"
convergenceEncryptionTag :: B.ByteString -> Parameters -> B.ByteString
convergenceEncryptionTag secret (Parameters segmentSize total _ required) =
tag
where
tag = B.concat [convergenceEncryptionTagPrefix, netstring secret, netstring paramTag]
paramTag = B.intercalate "," . map showBytes $ [requiredI, totalI, segmentSizeI]
requiredI = toInteger required
totalI = toInteger total
segmentSizeI = toInteger segmentSize
-- Compute the strict convergence encryption hash on a lazy data parameter.
convergenceEncryptionHashLazy :: B.ByteString -> Parameters -> BL.ByteString -> B.ByteString
convergenceEncryptionHashLazy secret params bytes =
-- It was somewhat helpful during development/debugging to make this
-- function return this instead:
--
-- BL.toStrict toHash
--
B.take convergenceSecretLength theSHA256d
where
theSHA256d = toBytes (hash theSHA256 :: Digest SHA256)
theSHA256 = toBytes (hashlazy toHash :: Digest SHA256)
toHash :: BL.ByteString
toHash = BL.concat [tag, bytes]
tag = BL.fromStrict . netstring $ convergenceEncryptionTag secret params
convergenceSecretLength :: ByteLength
convergenceSecretLength = 16
storageIndexLength :: ByteLength
storageIndexLength = 16