-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rename Sel.SecretKey.Cipher.Hash to Ciphertext #182
Open
intricate
wants to merge
1
commit into
haskell-cryptography:main
Choose a base branch
from
intricate:rename-sel-secretkey-cipher-hash
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,12 +34,12 @@ module Sel.SecretKey.Cipher | |
, nonceFromHexByteString | ||
, nonceToHexByteString | ||
|
||
-- ** Hash | ||
, Hash | ||
, hashFromHexByteString | ||
, hashToBinary | ||
, hashToHexByteString | ||
, hashToHexText | ||
-- ** Ciphertext | ||
, Ciphertext | ||
, ciphertextFromHexByteString | ||
, ciphertextToBinary | ||
, ciphertextToHexByteString | ||
, ciphertextToHexText | ||
) where | ||
|
||
import Control.Monad (void, when) | ||
|
@@ -75,7 +75,7 @@ import Sel.Internal.Sodium (binaryToHex) | |
-- $introduction | ||
-- "Authenticated Encryption" uses a secret key along with a single-use number | ||
-- called a "nonce" to encrypt a message. | ||
-- The resulting hash is accompanied by an authentication tag. | ||
-- The resulting ciphertext is accompanied by an authentication tag. | ||
-- | ||
-- Encryption is done with the XSalsa20 stream cipher and authentication is done with the | ||
-- Poly1305 MAC hash. | ||
|
@@ -255,16 +255,16 @@ nonceToHexByteString (Nonce nonceForeignPtr) = | |
-- | A ciphertext consisting of an encrypted message and an authentication tag. | ||
-- | ||
-- @since 0.0.1.0 | ||
data Hash = Hash | ||
data Ciphertext = Ciphertext | ||
{ messageLength :: CULLong | ||
, hashForeignPtr :: ForeignPtr CUChar | ||
, ciphertextForeignPtr :: ForeignPtr CUChar | ||
} | ||
|
||
-- | | ||
-- | ||
-- @since 0.0.1.0 | ||
instance Eq Hash where | ||
(Hash messageLength1 hk1) == (Hash messageLength2 hk2) = | ||
instance Eq Ciphertext where | ||
(Ciphertext messageLength1 hk1) == (Ciphertext messageLength2 hk2) = | ||
let | ||
messageLength = messageLength1 == messageLength2 | ||
content = | ||
|
@@ -278,8 +278,8 @@ instance Eq Hash where | |
-- | | ||
-- | ||
-- @since 0.0.1.0 | ||
instance Ord Hash where | ||
compare (Hash messageLength1 hk1) (Hash messageLength2 hk2) = | ||
instance Ord Ciphertext where | ||
compare (Ciphertext messageLength1 hk1) (Ciphertext messageLength2 hk2) = | ||
let | ||
messageLength = compare messageLength1 messageLength2 | ||
content = | ||
|
@@ -293,69 +293,70 @@ instance Ord Hash where | |
-- | ⚠️ Be prudent as to what you do with it! | ||
-- | ||
-- @since 0.0.1.0 | ||
instance Display Hash where | ||
displayBuilder = Builder.fromText . hashToHexText | ||
instance Display Ciphertext where | ||
displayBuilder = Builder.fromText . ciphertextToHexText | ||
|
||
-- | ⚠️ Be prudent as to what you do with it! | ||
-- | ||
-- @since 0.0.1.0 | ||
instance Show Hash where | ||
show = BS.unpackChars . hashToHexByteString | ||
instance Show Ciphertext where | ||
show = BS.unpackChars . ciphertextToHexByteString | ||
|
||
-- | Create a 'Hash' from a binary 'StrictByteString' that you have obtained on your own, | ||
-- usually from the network or disk. It must be a valid hash built from the concatenation | ||
-- of the encrypted message and the authentication tag. | ||
-- | Create a 'Ciphertext' from a hexadecimal-encoded 'StrictByteString' that | ||
-- you have obtained on your own, usually from the network or disk. It must be | ||
-- a valid ciphertext built from the concatenation of the encrypted message and | ||
-- the authentication tag. | ||
Comment on lines
-305
to
+308
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any idea what line width we're generally targeting? I changed this to 80 chars when updating the docs, but I'm happy to comply with whatever you prefer. |
||
-- | ||
-- The input hash must at least of length 'cryptoSecretboxMACBytes' | ||
-- The input ciphertext must at least of length 'cryptoSecretboxMACBytes'. | ||
-- | ||
-- @since 0.0.1.0 | ||
hashFromHexByteString :: StrictByteString -> Either Text Hash | ||
hashFromHexByteString hexHash = unsafeDupablePerformIO $ | ||
case Base16.decodeBase16Untyped hexHash of | ||
ciphertextFromHexByteString :: StrictByteString -> Either Text Ciphertext | ||
ciphertextFromHexByteString hexCiphertext = unsafeDupablePerformIO $ | ||
case Base16.decodeBase16Untyped hexCiphertext of | ||
Right bytestring -> | ||
if BS.length bytestring >= fromIntegral cryptoSecretboxMACBytes | ||
then BS.unsafeUseAsCStringLen bytestring $ \(outsideHashPtr, outsideHashLength) -> do | ||
hashForeignPtr <- BS.mallocByteString @CChar outsideHashLength -- The foreign pointer that will receive the hash data. | ||
Foreign.withForeignPtr hashForeignPtr $ \hashPtr -> | ||
-- We copy bytes from 'outsideHashPtr' to 'hashPtr'. | ||
Foreign.copyArray hashPtr outsideHashPtr outsideHashLength | ||
then BS.unsafeUseAsCStringLen bytestring $ \(outsideCiphertextPtr, outsideCiphertextLength) -> do | ||
ciphertextForeignPtr <- BS.mallocByteString @CChar outsideCiphertextLength -- The foreign pointer that will receive the ciphertext data. | ||
Foreign.withForeignPtr ciphertextForeignPtr $ \ciphertextPtr -> | ||
-- We copy bytes from 'outsideCiphertextPtr' to 'ciphertextPtr'. | ||
Foreign.copyArray ciphertextPtr outsideCiphertextPtr outsideCiphertextLength | ||
pure $ | ||
Right $ | ||
Hash | ||
(fromIntegral @Int @CULLong outsideHashLength - fromIntegral @CSize @CULLong cryptoSecretboxMACBytes) | ||
(Foreign.castForeignPtr @CChar @CUChar hashForeignPtr) | ||
else pure $ Left $ Text.pack "Hash is too short" | ||
Ciphertext | ||
(fromIntegral @Int @CULLong outsideCiphertextLength - fromIntegral @CSize @CULLong cryptoSecretboxMACBytes) | ||
(Foreign.castForeignPtr @CChar @CUChar ciphertextForeignPtr) | ||
else pure $ Left $ Text.pack "Ciphertext is too short" | ||
Left msg -> pure $ Left msg | ||
|
||
-- | Convert a 'Hash' to a hexadecimal-encoded 'Text'. | ||
-- | Convert a 'Ciphertext' to a hexadecimal-encoded 'Text'. | ||
-- | ||
-- ⚠️ Be prudent as to where you store it! | ||
-- | ||
-- @since 0.0.1.0 | ||
hashToHexText :: Hash -> Text | ||
hashToHexText = Base16.extractBase16 . Base16.encodeBase16 . hashToBinary | ||
ciphertextToHexText :: Ciphertext -> Text | ||
ciphertextToHexText = Base16.extractBase16 . Base16.encodeBase16 . ciphertextToBinary | ||
|
||
-- | Convert a 'Hash' to a hexadecimal-encoded 'StrictByteString' in constant time. | ||
-- | Convert a 'Ciphertext' to a hexadecimal-encoded 'StrictByteString' in constant time. | ||
-- | ||
-- ⚠️ Be prudent as to where you store it! | ||
-- | ||
-- @since 0.0.1.0 | ||
hashToHexByteString :: Hash -> StrictByteString | ||
hashToHexByteString (Hash messageLength fPtr) = | ||
ciphertextToHexByteString :: Ciphertext -> StrictByteString | ||
ciphertextToHexByteString (Ciphertext messageLength fPtr) = | ||
binaryToHex fPtr (cryptoSecretboxMACBytes + fromIntegral messageLength) | ||
|
||
-- | Convert a 'Hash' to a binary 'StrictByteString'. | ||
-- | Convert a 'Ciphertext' to a binary 'StrictByteString'. | ||
-- | ||
-- ⚠️ Be prudent as to where you store it! | ||
-- | ||
-- @since 0.0.1.0 | ||
hashToBinary :: Hash -> StrictByteString | ||
hashToBinary (Hash messageLength fPtr) = | ||
ciphertextToBinary :: Ciphertext -> StrictByteString | ||
ciphertextToBinary (Ciphertext messageLength fPtr) = | ||
BS.fromForeignPtr0 | ||
(Foreign.castForeignPtr fPtr) | ||
(fromIntegral messageLength + fromIntegral cryptoSecretboxMACBytes) | ||
|
||
-- | Create an authenticated hash from a message, a secret key, | ||
-- | Create an authenticated ciphertext from a message, a secret key, | ||
-- and a one-time cryptographic nonce that must never be re-used with the same | ||
-- secret key to encrypt another message. | ||
-- | ||
|
@@ -365,46 +366,46 @@ encrypt | |
-- ^ Message to encrypt. | ||
-> SecretKey | ||
-- ^ Secret key generated with 'newSecretKey'. | ||
-> IO (Nonce, Hash) | ||
-> IO (Nonce, Ciphertext) | ||
encrypt message (SecretKey secretKeyForeignPtr) = | ||
BS.unsafeUseAsCStringLen message $ \(cString, cStringLen) -> do | ||
(Nonce nonceForeignPtr) <- newNonce | ||
hashForeignPtr <- | ||
ciphertextForeignPtr <- | ||
Foreign.mallocForeignPtrBytes | ||
(cStringLen + fromIntegral cryptoSecretboxMACBytes) | ||
Foreign.withForeignPtr hashForeignPtr $ \hashPtr -> | ||
Foreign.withForeignPtr ciphertextForeignPtr $ \ciphertextPtr -> | ||
Foreign.withForeignPtr secretKeyForeignPtr $ \secretKeyPtr -> | ||
Foreign.withForeignPtr nonceForeignPtr $ \noncePtr -> do | ||
void $ | ||
cryptoSecretboxEasy | ||
hashPtr | ||
ciphertextPtr | ||
(Foreign.castPtr @CChar @CUChar cString) | ||
(fromIntegral @Int @CULLong cStringLen) | ||
noncePtr | ||
secretKeyPtr | ||
let hash = Hash (fromIntegral @Int @CULLong cStringLen) hashForeignPtr | ||
pure (Nonce nonceForeignPtr, hash) | ||
let ciphertext = Ciphertext (fromIntegral @Int @CULLong cStringLen) ciphertextForeignPtr | ||
pure (Nonce nonceForeignPtr, ciphertext) | ||
|
||
-- | Decrypt a hashed and authenticated message with the shared secret key and the one-time cryptographic nonce. | ||
-- | Decrypt an encrypted and authenticated message with the shared secret key and the one-time cryptographic nonce. | ||
-- | ||
-- @since 0.0.1.0 | ||
decrypt | ||
:: Hash | ||
:: Ciphertext | ||
-- ^ Encrypted message you want to decrypt. | ||
-> SecretKey | ||
-- ^ Secret key used for encrypting the original message. | ||
-> Nonce | ||
-- ^ Nonce used for encrypting the original message. | ||
-> Maybe StrictByteString | ||
decrypt Hash{messageLength, hashForeignPtr} (SecretKey secretKeyForeignPtr) (Nonce nonceForeignPtr) = unsafeDupablePerformIO $ do | ||
decrypt Ciphertext{messageLength, ciphertextForeignPtr} (SecretKey secretKeyForeignPtr) (Nonce nonceForeignPtr) = unsafeDupablePerformIO $ do | ||
messagePtr <- Foreign.mallocBytes (fromIntegral @CULLong @Int messageLength) | ||
Foreign.withForeignPtr hashForeignPtr $ \hashPtr -> | ||
Foreign.withForeignPtr ciphertextForeignPtr $ \ciphertextPtr -> | ||
Foreign.withForeignPtr secretKeyForeignPtr $ \secretKeyPtr -> | ||
Foreign.withForeignPtr nonceForeignPtr $ \noncePtr -> do | ||
result <- | ||
cryptoSecretboxOpenEasy | ||
messagePtr | ||
hashPtr | ||
ciphertextPtr | ||
(messageLength + fromIntegral cryptoSecretboxMACBytes) | ||
noncePtr | ||
secretKeyPtr | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we prefer
Ciphertext
orCipherText
?I noticed a little bit of inconsistency:
In
Sel.PublicKey.Cipher
andSel.SecretKey.Stream
, we have two types namedCipherText
. However, inSel.SecretKey.Stream
, there are functions where this capitalization is not consistent:ciphertextFromHexByteString
,ciphertextToBinary
, etc.Just let me know which way you guys prefer and I can make the changes throughout the project, if you like.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've personally always used "ciphertext" as a single word but, of course, I'd like to comply with the API that you prefer.