{"action":"created","issue":{"url":"https://api.github.com/repos/haskell-crypto/cryptonite/issues/214","repository_url":"https://api.github.com/repos/haskell-crypto/cryptonite","labels_url":"https://api.github.com/repos/haskell-crypto/cryptonite/issues/214/labels{/name}","comments_url":"https://api.github.com/repos/haskell-crypto/cryptonite/issues/214/comments","events_url":"https://api.github.com/repos/haskell-crypto/cryptonite/issues/214/events","html_url":"https://github.com/haskell-crypto/cryptonite/issues/214","id":292846695,"number":214,"title":"Add equivalent of OpenSSL's EVP_BytesToKey (e.g. generate key and IV from some password)","user":{"login":"mgmeier","id":4739597,"avatar_url":"https://avatars1.githubusercontent.com/u/4739597?v=4","gravatar_id":"","url":"https://api.github.com/users/mgmeier","html_url":"https://github.com/mgmeier","followers_url":"https://api.github.com/users/mgmeier/followers","following_url":"https://api.github.com/users/mgmeier/following{/other_user}","gists_url":"https://api.github.com/users/mgmeier/gists{/gist_id}","starred_url":"https://api.github.com/users/mgmeier/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mgmeier/subscriptions","organizations_url":"https://api.github.com/users/mgmeier/orgs","repos_url":"https://api.github.com/users/mgmeier/repos","events_url":"https://api.github.com/users/mgmeier/events{/privacy}","received_events_url":"https://api.github.com/users/mgmeier/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2018-01-30T16:24:25Z","updated_at":"2018-03-07T20:31:09Z","closed_at":null,"author_association":"NONE","body":"Maybe I've overlooked it in the library, but would that be a feature worth adding?\r\n\r\nFor my current project, I adapted some code from here: https://hackage.haskell.org/package/shadowsocks-1.20151028/src/Shadowsocks/Encrypt.hs\r\n\r\n```\r\ncrypter :: ByteString -> ByteString -> ByteString\r\ncrypter password =\r\n    cbcEncrypt (cipher :: AES256) iv . pad (PKCS7 16)\r\n  where\r\n    (key, iv_)          = evpBytesToKey password 32 16      -- key size, iv size for AES256\r\n    Just iv             = makeIV iv_\r\n    CryptoPassed cipher = cipherInit key\r\n\r\n-- Haskell implementation of OpenSSL's EVP_BytesToKey\r\n-- generate key and iv from a given password\r\nevpBytesToKey :: ByteString -> Int -> Int -> (ByteString, ByteString)\r\nevpBytesToKey password keyLen ivLen =\r\n    let ms' = B.concat $ ms 0 []\r\n        key = B.take keyLen ms'\r\n        iv  = B.take ivLen $ B.drop keyLen ms'\r\n    in (key, iv)\r\n  where\r\n    hash' :: ByteString -> ByteString\r\n    hash' bs = convert (Crypto.hash bs :: Digest MD5)\r\n    \r\n    ms :: Int -> [ByteString] -> [ByteString]\r\n    ms 0 _ = ms 1 [hash' password]\r\n    ms i m\r\n        | B.length (B.concat m) < keyLen + ivLen =\r\n            ms (i+1) (m ++ [hash' (last m <> password)])\r\n        | otherwise = m\r\n```\r\n\r\nBeing just a quick hack, I see some things that would make it a good fit for adding it to `cryptonite`, like e.g.:\r\n* parametrize for different `Digest` (sometimes some SHA implementation is used)\r\n* adjust types (e.g. returning an `IV a` instead of a `ByteString`) to make it compose well with other primitives / functions in `cryptonite`\r\n* get key and IV length from the instance of `Cipher`\r\n* add optional salt to the byte sequence the `ms` function generates (as OpenSSL does) \r\n* optimize performance (strict vs. lazy `ByteString`)?\r\n\r\nWhat do you think?"},"comment":{"url":"https://api.github.com/repos/haskell-crypto/cryptonite/issues/comments/371274426","html_url":"https://github.com/haskell-crypto/cryptonite/issues/214#issuecomment-371274426","issue_url":"https://api.github.com/repos/haskell-crypto/cryptonite/issues/214","id":371274426,"user":{"login":"mgmeier","id":4739597,"avatar_url":"https://avatars1.githubusercontent.com/u/4739597?v=4","gravatar_id":"","url":"https://api.github.com/users/mgmeier","html_url":"https://github.com/mgmeier","followers_url":"https://api.github.com/users/mgmeier/followers","following_url":"https://api.github.com/users/mgmeier/following{/other_user}","gists_url":"https://api.github.com/users/mgmeier/gists{/gist_id}","starred_url":"https://api.github.com/users/mgmeier/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mgmeier/subscriptions","organizations_url":"https://api.github.com/users/mgmeier/orgs","repos_url":"https://api.github.com/users/mgmeier/repos","events_url":"https://api.github.com/users/mgmeier/events{/privacy}","received_events_url":"https://api.github.com/users/mgmeier/received_events","type":"User","site_admin":false},"created_at":"2018-03-07T20:31:09Z","updated_at":"2018-03-07T20:31:09Z","author_association":"NONE","body":"Of course, should you decide on including this as a utility function, I'd be willing to prepare a proper PR (using `ByteArray`, and providing sensible cipher context initialization)."}}
{"actor":{"display_login":"mgmeier"}}