Skip to content
This repository was archived by the owner on Sep 20, 2023. It is now read-only.

Add equivalent of OpenSSL's EVP_BytesToKey (e.g. generate key and IV from some password) #214

@mgmeier

Description

@mgmeier

Maybe I've overlooked it in the library, but would that be a feature worth adding?

For my current project, I adapted some code from here: https://hackage.haskell.org/package/shadowsocks-1.20151028/src/Shadowsocks/Encrypt.hs

crypter :: ByteString -> ByteString -> ByteString
crypter password =
    cbcEncrypt (cipher :: AES256) iv . pad (PKCS7 16)
  where
    (key, iv_)          = evpBytesToKey password 32 16      -- key size, iv size for AES256
    Just iv             = makeIV iv_
    CryptoPassed cipher = cipherInit key

-- Haskell implementation of OpenSSL's EVP_BytesToKey
-- generate key and iv from a given password
evpBytesToKey :: ByteString -> Int -> Int -> (ByteString, ByteString)
evpBytesToKey password keyLen ivLen =
    let ms' = B.concat $ ms 0 []
        key = B.take keyLen ms'
        iv  = B.take ivLen $ B.drop keyLen ms'
    in (key, iv)
  where
    hash' :: ByteString -> ByteString
    hash' bs = convert (Crypto.hash bs :: Digest MD5)
    
    ms :: Int -> [ByteString] -> [ByteString]
    ms 0 _ = ms 1 [hash' password]
    ms i m
        | B.length (B.concat m) < keyLen + ivLen =
            ms (i+1) (m ++ [hash' (last m <> password)])
        | otherwise = m

Being just a quick hack, I see some things that would make it a good fit for adding it to cryptonite, like e.g.:

  • parametrize for different Digest (sometimes some SHA implementation is used)
  • adjust types (e.g. returning an IV a instead of a ByteString) to make it compose well with other primitives / functions in cryptonite
  • get key and IV length from the instance of Cipher
  • add optional salt to the byte sequence the ms function generates (as OpenSSL does)
  • optimize performance (strict vs. lazy ByteString)?

What do you think?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions