Encryption: implement RFC9106 recommendations

This commit is contained in:
La Ancapo 2026-01-27 03:05:59 +01:00
parent 559900fd3a
commit 97cdc074f9

View file

@ -41,17 +41,18 @@ xorWithKey key bs
| B.null key = error "key must not be empty" | B.null key = error "key must not be empty"
| otherwise = B.pack $ B.zipWith xor bs key | otherwise = B.pack $ B.zipWith xor bs key
-- as recommended by RFC9106
argonOptions = defaultOptions { variant = Argon2id }
-- format: E[16-byte salt][4-byte big-endian iterations][ciphertext] -- format: E[16-byte salt][4-byte big-endian iterations][ciphertext]
encryptData :: ByteString -> IO ByteString encryptData :: ByteString -> IO ByteString
encryptData privkey = do encryptData privkey = do
iterationTime <- measureIteration iterationTime <- measureIteration
print iterationTime let minIterations = 3 -- as recommended by RFC9106
let iterations = ceiling $ 1 / iterationTime let iterations = max minIterations $ ceiling $ 1 / iterationTime
print iterations
salt <- getEntropy 16 :: IO ByteString salt <- getEntropy 16 :: IO ByteString
--let password = "password" :: ByteString
password <- getPassword password <- getPassword
key <- throwCryptoErrorIO $ hash defaultOptions { iterations = iterations } password salt 56 :: IO ByteString key <- throwCryptoErrorIO $ hash argonOptions { iterations = iterations } password salt 56 :: IO ByteString
let ciphertext = xorWithKey key privkey let ciphertext = xorWithKey key privkey
-- encode iterations as Word32 big-endian -- encode iterations as Word32 big-endian
let iterWord :: Word32 let iterWord :: Word32
@ -67,7 +68,7 @@ decryptData contents = do
let (salt, rest) = B.splitAt 16 contents let (salt, rest) = B.splitAt 16 contents
(iterBytes, ciphertext) = B.splitAt 4 rest (iterBytes, ciphertext) = B.splitAt 4 rest
iterations = runGet getWord32be (BL.fromStrict iterBytes) iterations = runGet getWord32be (BL.fromStrict iterBytes)
key <- throwCryptoErrorIO $ hash defaultOptions { iterations = iterations } password salt 56 :: IO ByteString key <- throwCryptoErrorIO $ hash argonOptions { iterations = iterations } password salt 56 :: IO ByteString
let plaintext = xorWithKey key ciphertext let plaintext = xorWithKey key ciphertext
case B.head plaintext of case B.head plaintext of
0x53 -> pure plaintext 0x53 -> pure plaintext