packages feed

webauthn 0.7.0.0 → 0.8.0.0

raw patch · 22 files changed

+489/−163 lines, 22 filesdep ~aesondep ~basedep ~bytestring

Dependency ranges changed: aeson, base, bytestring, text, these, time

Files

changelog.md view
@@ -1,6 +1,11 @@+### 0.8.0.0++* [#178](https://github.com/tweag/webauthn/pull/178) Remove orphan instance for ToJSON ByteString.+  Use newtypes for the binary data including the PNG icons for authenticators and the cryptographic values.+ ### 0.7.0.0 -* [174](https://github.com/tweag/webauthn/pull/174) Correctly verify packed+* [#174](https://github.com/tweag/webauthn/pull/174) Correctly verify packed   attestation when the AAGUID extension of the certitificate is missing. This is   a backwards-incompatible change for packed attestation responses that   previously failed due to the missing AAGUID extension. These responses now
src/Crypto/WebAuthn/AttestationStatementFormat/AndroidKey.hs view
@@ -29,7 +29,6 @@ import Data.Aeson (ToJSON, object, toJSON, (.=)) import Data.Bifunctor (first) import Data.ByteArray (convert)-import Data.ByteString (ByteString) import Data.HashMap.Strict ((!?)) import Data.List.NonEmpty (NonEmpty ((:|)), toList) import qualified Data.List.NonEmpty as NE@@ -155,7 +154,7 @@  -- | [(spec)](https://www.w3.org/TR/webauthn-2/#sctn-android-key-attestation) data Statement = Statement-  { sig :: ByteString,+  { sig :: Cose.Signature,     x5c :: NonEmpty X509.SignedCertificate,     -- | Holds both the "alg" from the statement and the public key from the     -- X.509 certificate@@ -237,7 +236,7 @@    asfDecode _ xs =     case (xs !? "alg", xs !? "sig", xs !? "x5c") of-      (Just (CBOR.TInt algId), Just (CBOR.TBytes sig), Just (CBOR.TList (NE.nonEmpty -> Just x5cRaw))) -> do+      (Just (CBOR.TInt algId), Just (CBOR.TBytes (Cose.Signature -> sig)), Just (CBOR.TList (NE.nonEmpty -> Just x5cRaw))) -> do         alg <- Cose.toCoseSignAlg algId         x5c@(credCert :| _) <- forM x5cRaw $ \case           CBOR.TBytes certBytes ->@@ -260,7 +259,7 @@    asfEncode _ Statement {..} =     CBOR.TMap-      [ (CBOR.TString "sig", CBOR.TBytes sig),+      [ (CBOR.TString "sig", CBOR.TBytes $ Cose.unSignature sig),         (CBOR.TString "alg", CBOR.TInt $ Cose.fromCoseSignAlg $ Cose.signAlg pubKeyAndAlg),         ( CBOR.TString "x5c",           CBOR.TList $@@ -278,7 +277,7 @@      -- 2. Verify that sig is a valid signature over the concatenation of authenticatorData and clientDataHash using the     -- public key in the first certificate in x5c with the algorithm specified in alg.-    let signedData = rawData <> convert (M.unClientDataHash clientDataHash)+    let signedData = Cose.Message $ rawData <> convert (M.unClientDataHash clientDataHash)     case Cose.verify pubKeyAndAlg signedData sig of       Right () -> pure ()       Left err -> failure $ VerificationFailure err
src/Crypto/WebAuthn/AttestationStatementFormat/FidoU2F.hs view
@@ -18,6 +18,7 @@ import Control.Monad (unless) import Crypto.PubKey.ECC.Types (CurveName (SEC_p256r1)) import qualified Crypto.WebAuthn.Cose.PublicKeyWithSignAlg as Cose+import Crypto.WebAuthn.Internal.ToJSONOrphans (PrettyHexByteString (PrettyHexByteString)) import Crypto.WebAuthn.Internal.Utils (failure) import qualified Crypto.WebAuthn.Model.Types as M import Data.Aeson (ToJSON, object, toJSON, (.=))@@ -66,7 +67,7 @@   toJSON Statement {..} =     object       [ "attestnCert" .= attCert,-        "sig" .= sig+        "sig" .= PrettyHexByteString sig       ]  instance M.AttestationStatementFormat Format where
src/Crypto/WebAuthn/AttestationStatementFormat/Packed.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ViewPatterns #-}  -- | Stability: experimental -- This module implements the@@ -25,7 +26,6 @@ import Data.Aeson (ToJSON, object, toJSON, (.=)) import Data.Bifunctor (first) import Data.ByteArray (convert)-import qualified Data.ByteString as BS import Data.HashMap.Strict ((!?)) import Data.List.NonEmpty (NonEmpty ((:|)), toList) import qualified Data.List.NonEmpty as NE@@ -45,7 +45,7 @@ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#sctn-packed-attestation) data Statement = Statement   { alg :: Cose.CoseSignAlg,-    sig :: BS.ByteString,+    sig :: Cose.Signature,     -- The AAGUID extension is optional     x5c :: Maybe (NE.NonEmpty X509.SignedCertificate, Maybe IdFidoGenCeAAGUID)   }@@ -98,7 +98,7 @@    asfDecode _ xs =     case (xs !? "alg", xs !? "sig", xs !? "x5c") of-      (Just (CBOR.TInt algId), Just (CBOR.TBytes sig), mx5c) -> do+      (Just (CBOR.TInt algId), Just (CBOR.TBytes (Cose.Signature -> sig)), mx5c) -> do         alg <- Cose.toCoseSignAlg algId         x5c <- case mx5c of           Nothing -> pure Nothing@@ -123,7 +123,7 @@    asfEncode _ Statement {..} =     CBOR.TMap-      ( [ (CBOR.TString "sig", CBOR.TBytes sig),+      ( [ (CBOR.TString "sig", CBOR.TBytes $ Cose.unSignature sig),           (CBOR.TString "alg", CBOR.TInt $ Cose.fromCoseSignAlg alg)         ]           ++ case x5c of@@ -142,7 +142,7 @@     Statement {alg = stmtAlg, sig = stmtSig, x5c = stmtx5c}     M.AuthenticatorData {M.adRawData = M.WithRaw rawData, M.adAttestedCredentialData = credData}     clientDataHash = do-      let signedData = rawData <> convert (M.unClientDataHash clientDataHash)+      let signedData = Cose.Message $ rawData <> convert (M.unClientDataHash clientDataHash)       case stmtx5c of         -- Self attestation         Nothing -> do@@ -165,7 +165,8 @@               pubKey = X509.certPubKey cert           -- Verify that sig is a valid signature over the concatenation of authenticatorData and clientDataHash using           -- the attestation public key in attestnCert with the algorithm specified in alg.-          case X509.verifySignature (X509.SignatureALG X509.HashSHA256 X509.PubKeyALG_EC) pubKey signedData stmtSig of+          -- FIXME: This is wrong, we should use alg!+          case X509.verifySignature (X509.SignatureALG X509.HashSHA256 X509.PubKeyALG_EC) pubKey (Cose.unMessage signedData) (Cose.unSignature stmtSig) of             X509.SignaturePass -> pure ()             X509.SignatureFailed err -> failure $ VerificationFailure err 
src/Crypto/WebAuthn/AttestationStatementFormat/TPM.hs view
@@ -26,6 +26,7 @@ import qualified Crypto.WebAuthn.Cose.PublicKey as Cose import qualified Crypto.WebAuthn.Cose.PublicKeyWithSignAlg as Cose import qualified Crypto.WebAuthn.Cose.SignAlg as Cose+import Crypto.WebAuthn.Internal.ToJSONOrphans (PrettyHexByteString (PrettyHexByteString)) import Crypto.WebAuthn.Internal.Utils (IdFidoGenCeAAGUID (IdFidoGenCeAAGUID), failure) import Crypto.WebAuthn.Model.Identifier (AAGUID) import qualified Crypto.WebAuthn.Model.Types as M@@ -124,8 +125,8 @@ -- | The TPMS_CERTIFY_INFO structure as specified in [TPMv2-Part2](https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf) -- section 10.12.3. data TPMSCertifyInfo = TPMSCertifyInfo-  { tpmsciName :: BS.ByteString,-    tpmsciQualifiedName :: BS.ByteString+  { tpmsciName :: PrettyHexByteString,+    tpmsciQualifiedName :: PrettyHexByteString   }   deriving (Eq, Show, Generic, ToJSON) @@ -135,8 +136,8 @@ data TPMSAttest = TPMSAttest   { tpmsaMagic :: Word32,     tpmsaType :: Word16,-    tpmsaQualifiedSigner :: BS.ByteString,-    tpmsaExtraData :: BS.ByteString,+    tpmsaQualifiedSigner :: PrettyHexByteString,+    tpmsaExtraData :: PrettyHexByteString,     tpmsaClockInfo :: TPMSClockInfo,     tpmsaFirmwareVersion :: Word64,     tpmsaAttested :: TPMSCertifyInfo@@ -170,10 +171,10 @@ -- [TPMv2-Part2](https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf) -- section 12.2.3.2. data TPMUPublicId-  = TPM2BPublicKeyRSA BS.ByteString+  = TPM2BPublicKeyRSA PrettyHexByteString   | TPMSECCPoint-      { tpmseX :: BS.ByteString,-        tpmseY :: BS.ByteString+      { tpmseX :: PrettyHexByteString,+        tpmseY :: PrettyHexByteString       }   deriving (Eq, Show, Generic, ToJSON) @@ -183,7 +184,7 @@     tpmtpNameAlg :: TPMAlgId,     tpmtpNameAlgRaw :: Word16,     tpmtpObjectAttributes :: TPMAObject,-    tpmtpAuthPolicy :: BS.ByteString,+    tpmtpAuthPolicy :: PrettyHexByteString,     tpmtpParameters :: TPMUPublicParms,     tpmtpUnique :: TPMUPublicId   }@@ -204,6 +205,12 @@   }   deriving (Eq, Show) +newtype CertInfoBytes = CertInfoBytes {unCertInfoBytes :: BS.ByteString}+  deriving newtype (Eq, Show)++newtype PubAreaBytes = PubAreaBytes {unPubAreaBytes :: BS.ByteString}+  deriving newtype (Eq, Show)+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#sctn-tpm-attestation) data Statement = Statement   { x5c :: NE.NonEmpty X509.SignedCertificate,@@ -214,11 +221,11 @@     aaguidExt :: Maybe IdFidoGenCeAAGUID,     extendedKeyUsage :: [X509.ExtKeyUsagePurpose],     basicConstraintsCA :: Bool,-    sig :: BS.ByteString,+    sig :: Cose.Signature,     certInfo :: TPMSAttest,-    certInfoRaw :: BS.ByteString,+    certInfoRaw :: CertInfoBytes,     pubArea :: TPMTPublic,-    pubAreaRaw :: BS.ByteString,+    pubAreaRaw :: PubAreaBytes,     pubAreaKey :: Cose.PublicKey   }   deriving (Eq, Show)@@ -357,49 +364,57 @@    asfDecode _ xs =     case (xs !? "ver", xs !? "alg", xs !? "x5c", xs !? "sig", xs !? "certInfo", xs !? "pubArea") of-      (Just (CBOR.TString "2.0"), Just (CBOR.TInt algId), Just (CBOR.TList (NE.nonEmpty -> Just x5cRaw)), Just (CBOR.TBytes sig), Just (CBOR.TBytes certInfoRaw), Just (CBOR.TBytes pubAreaRaw)) ->-        do-          x5c@(signedAikCert :| _) <- forM x5cRaw $ \case-            CBOR.TBytes certBytes ->-              first (("Failed to decode signed certificate: " <>) . Text.pack) (X509.decodeSignedCertificate certBytes)-            cert ->-              Left $ "Certificate CBOR value is not bytes: " <> Text.pack (show cert)-          alg <- Cose.toCoseSignAlg algId-          -- The get interface requires lazy bytestrings but we typically use-          -- strict bytestrings in the library, so we have to convert between-          -- them-          certInfo <- case Get.runGetOrFail getTPMAttest (LBS.fromStrict certInfoRaw) of-            Left (_, _, err) -> Left $ "Failed to decode certInfo: " <> Text.pack (show err)-            Right (_, _, res) -> pure res-          pubArea <- case Get.runGetOrFail getTPMTPublic (LBS.fromStrict pubAreaRaw) of-            Left (_, _, err) -> Left $ "Failed to decode pubArea: " <> Text.pack (show err)-            Right (_, _, res) -> pure res-          pubAreaKey <- extractPublicKey pubArea+      ( Just (CBOR.TString "2.0"),+        Just (CBOR.TInt algId),+        Just (CBOR.TList (NE.nonEmpty -> Just x5cRaw)),+        Just (CBOR.TBytes (Cose.Signature -> sig)),+        Just (CBOR.TBytes (CertInfoBytes -> certInfoRaw)),+        Just (CBOR.TBytes (PubAreaBytes -> pubAreaRaw))+        ) ->+          do+            x5c@(signedAikCert :| _) <- forM x5cRaw $ \case+              CBOR.TBytes certBytes ->+                first (("Failed to decode signed certificate: " <>) . Text.pack) (X509.decodeSignedCertificate certBytes)+              cert ->+                Left $ "Certificate CBOR value is not bytes: " <> Text.pack (show cert)+            alg <- Cose.toCoseSignAlg algId+            -- The get interface requires lazy bytestrings but we typically use+            -- strict bytestrings in the library, so we have to convert between+            -- them+            certInfo <- decodeCertInfoBytes certInfoRaw+            pubArea <- decodePubAreaBytes pubAreaRaw+            pubAreaKey <- extractPublicKey pubArea -          let aikCert = X509.getCertificate signedAikCert+            let aikCert = X509.getCertificate signedAikCert -          aikCertPubKey <- Cose.fromX509 $ X509.certPubKey aikCert-          aikPubKeyAndAlg <- Cose.makePublicKeyWithSignAlg aikCertPubKey alg+            aikCertPubKey <- Cose.fromX509 $ X509.certPubKey aikCert+            aikPubKeyAndAlg <- Cose.makePublicKeyWithSignAlg aikCertPubKey alg -          subjectAlternativeName <- case X509.extensionGetE (X509.certExtensions aikCert) of-            Just (Right ext) -> pure ext-            Just (Left err) -> Left $ "Failed to decode certificate subject alternative name extension: " <> Text.pack err-            Nothing -> Left "Certificate subject alternative name extension is missing"-          aaguidExt <- case X509.extensionGetE (X509.certExtensions aikCert) of-            Just (Right ext) -> pure $ Just ext-            Just (Left err) -> Left $ "Failed to decode certificate aaguid extension: " <> Text.pack err-            Nothing -> pure Nothing-          X509.ExtExtendedKeyUsage extendedKeyUsage <- case X509.extensionGetE (X509.certExtensions aikCert) of-            Just (Right ext) -> pure ext-            Just (Left err) -> Left $ "Failed to decode certificate extended key usage extension: " <> Text.pack err-            Nothing -> Left "Certificate extended key usage extension is missing"-          X509.ExtBasicConstraints basicConstraintsCA _ <- case X509.extensionGetE (X509.certExtensions aikCert) of-            Just (Right ext) -> pure ext-            Just (Left err) -> Left $ "Failed to decode certificate basic constraints extension: " <> Text.pack err-            Nothing -> Left "Certificate basic constraints extension is missing"-          Right $ Statement {..}+            subjectAlternativeName <- case X509.extensionGetE (X509.certExtensions aikCert) of+              Just (Right ext) -> pure ext+              Just (Left err) -> Left $ "Failed to decode certificate subject alternative name extension: " <> Text.pack err+              Nothing -> Left "Certificate subject alternative name extension is missing"+            aaguidExt <- case X509.extensionGetE (X509.certExtensions aikCert) of+              Just (Right ext) -> pure $ Just ext+              Just (Left err) -> Left $ "Failed to decode certificate aaguid extension: " <> Text.pack err+              Nothing -> pure Nothing+            X509.ExtExtendedKeyUsage extendedKeyUsage <- case X509.extensionGetE (X509.certExtensions aikCert) of+              Just (Right ext) -> pure ext+              Just (Left err) -> Left $ "Failed to decode certificate extended key usage extension: " <> Text.pack err+              Nothing -> Left "Certificate extended key usage extension is missing"+            X509.ExtBasicConstraints basicConstraintsCA _ <- case X509.extensionGetE (X509.certExtensions aikCert) of+              Just (Right ext) -> pure ext+              Just (Left err) -> Left $ "Failed to decode certificate basic constraints extension: " <> Text.pack err+              Nothing -> Left "Certificate basic constraints extension is missing"+            Right $ Statement {..}       _ -> Left $ "CBOR map didn't have expected value types (ver: \"2.0\", alg: int, x5c: non-empty list, sig: bytes, certInfo: bytes, pubArea: bytes): " <> Text.pack (show xs)     where+      decodeCertInfoBytes :: CertInfoBytes -> Either Text TPMSAttest+      decodeCertInfoBytes (CertInfoBytes bytes) =+        case Get.runGetOrFail getTPMAttest (LBS.fromStrict bytes) of+          Left (_, _, err) -> Left $ "Failed to decode certInfo: " <> Text.pack (show err)+          Right (_, _, res) -> pure res+       getTPMAttest :: Get.Get TPMSAttest       getTPMAttest = do         tpmsaMagic <- Get.getWord32be@@ -427,11 +442,17 @@         tpmsciQualifiedName <- getTPMByteString         pure TPMSCertifyInfo {..} -      getTPMByteString :: Get.Get BS.ByteString+      getTPMByteString :: Get.Get PrettyHexByteString       getTPMByteString = do         size <- Get.getWord16be-        Get.getByteString (fromIntegral size)+        PrettyHexByteString <$> Get.getByteString (fromIntegral size) +      decodePubAreaBytes :: PubAreaBytes -> Either Text TPMTPublic+      decodePubAreaBytes (PubAreaBytes bytes) =+        case Get.runGetOrFail getTPMTPublic (LBS.fromStrict bytes) of+          Left (_, _, err) -> Left $ "Failed to decode certInfo: " <> Text.pack (show err)+          Right (_, _, res) -> pure res+       getTPMTPublic :: Get.Get TPMTPublic       getTPMTPublic = do         tpmtpType <- toTPMAlgId =<< Get.getWord16be@@ -479,7 +500,7 @@         TPMTPublic           { tpmtpType = TPMAlgRSA,             tpmtpParameters = TPMSRSAParms {..},-            tpmtpUnique = TPM2BPublicKeyRSA nb+            tpmtpUnique = TPM2BPublicKeyRSA (PrettyHexByteString nb)           } =           Cose.checkPublicKey             Cose.PublicKeyRSA@@ -490,7 +511,7 @@         TPMTPublic           { tpmtpType = TPMAlgECC,             tpmtpParameters = TPMSECCParms {..},-            tpmtpUnique = TPMSECCPoint {..}+            tpmtpUnique = TPMSECCPoint {tpmseX = PrettyHexByteString tpmseX, tpmseY = PrettyHexByteString tpmseY}           } =           Cose.checkPublicKey             Cose.PublicKeyECDSA@@ -507,9 +528,9 @@         ( CBOR.TString "x5c",           CBOR.TList $ map (CBOR.TBytes . X509.encodeSignedObject) $ NE.toList x5c         ),-        (CBOR.TString "sig", CBOR.TBytes sig),-        (CBOR.TString "certInfo", CBOR.TBytes certInfoRaw),-        (CBOR.TString "pubArea", CBOR.TBytes pubAreaRaw)+        (CBOR.TString "sig", CBOR.TBytes $ Cose.unSignature sig),+        (CBOR.TString "certInfo", CBOR.TBytes $ unCertInfoBytes certInfoRaw),+        (CBOR.TString "pubArea", CBOR.TBytes $ unPubAreaBytes pubAreaRaw)       ]    type AttStmtVerificationError Format = VerificationError@@ -546,7 +567,7 @@       -- the hash algorithm employed in "alg".       case hashWithCorrectAlgorithm (Cose.signAlg aikPubKeyAndAlg) attToBeSigned of         Just attHash -> do-          let extraData = tpmsaExtraData certInfo+          let PrettyHexByteString extraData = tpmsaExtraData certInfo           unless (attHash == extraData) . failure $ HashMismatch attHash extraData           pure ()         Nothing -> failure HashFunctionUnknown@@ -557,8 +578,8 @@       -- nameAlg field of pubArea using the procedure specified in       -- [TPMv2-Part1] section 16.       let mPubAreaHash = case tpmtpNameAlg pubArea of-            TPMAlgSHA1 -> Right $ BA.convert $ hashWith SHA1 pubAreaRaw-            TPMAlgSHA256 -> Right $ BA.convert $ hashWith SHA256 pubAreaRaw+            TPMAlgSHA1 -> Right $ BA.convert $ hashWith SHA1 $ unPubAreaBytes pubAreaRaw+            TPMAlgSHA256 -> Right $ BA.convert $ hashWith SHA256 $ unPubAreaBytes pubAreaRaw             TPMAlgECC -> Left TPMAlgECC             TPMAlgRSA -> Left TPMAlgRSA @@ -569,7 +590,7 @@                   Put.putWord16be (tpmtpNameAlgRaw pubArea)                   Put.putByteString pubAreaHash -          let name = tpmsciName (tpmsaAttested certInfo)+          let PrettyHexByteString name = tpmsciName (tpmsaAttested certInfo)           unless (name == pubName) . failure $ NameMismatch pubName name           pure ()         Left alg -> failure $ NameAlgorithmInvalid alg@@ -585,7 +606,7 @@        -- 4.8 Verify the sig is a valid signature over certInfo using the       -- attestation public key in aikCert with the algorithm specified in alg.-      case Cose.verify aikPubKeyAndAlg certInfoRaw sig of+      case Cose.verify aikPubKeyAndAlg (Cose.Message $ unCertInfoBytes certInfoRaw) sig of         Right () -> pure ()         Left err -> failure $ VerificationFailure err 
src/Crypto/WebAuthn/Cose/Internal/Verify.hs view
@@ -25,6 +25,8 @@     fromX509,      -- * Signature verification+    Cose.Message (..),+    Cose.Signature (..),     verify,      -- * Hash Conversions to cryptonite types@@ -46,7 +48,6 @@ import qualified Crypto.WebAuthn.Cose.PublicKey as Cose import qualified Crypto.WebAuthn.Cose.PublicKeyWithSignAlg as Cose import qualified Crypto.WebAuthn.Cose.SignAlg as Cose-import Crypto.WebAuthn.Internal.ToJSONOrphans () import qualified Data.ASN1.BinaryEncoding as ASN1 import qualified Data.ASN1.Encoding as ASN1 import qualified Data.ASN1.Types as ASN1@@ -63,7 +64,7 @@   Cose.checkPublicKey     Cose.PublicKeyEdDSA       { eddsaCurve = Cose.CoseCurveEd25519,-        eddsaX = convert key+        eddsaX = Cose.EdDSAKeyBytes $ convert key       } fromX509 (X509.PubKeyEC X509.PubKeyEC_Named {..}) = do   let curve = ECC.getCurveByName pubkeyEC_name@@ -87,7 +88,8 @@ -- 'Cose.PublicKeyWithSignAlg' Returns an error if the signature algorithm -- doesn't match. Also returns an error if the signature wasn't valid or for -- other errors.-verify :: Cose.PublicKeyWithSignAlg -> BS.ByteString -> BS.ByteString -> Either Text ()+-- FIXME: https://w3c.github.io/webauthn/#sctn-signature-attestation-types kind of documents this, but not for all formats. This is notably not really related to COSE, but rather webauthn's own definitions. The spec should be made less ambiguous, file upstream issues and refactor this code+verify :: Cose.PublicKeyWithSignAlg -> Cose.Message -> Cose.Signature -> Either Text () verify   Cose.PublicKeyWithSignAlg     { publicKey = Cose.PublicKey Cose.PublicKeyEdDSA {eddsaCurve = Cose.CoseCurveEd25519, ..},@@ -95,13 +97,13 @@     }   msg   sig = do-    key <- case Ed25519.publicKey eddsaX of+    key <- case Ed25519.publicKey $ Cose.unEdDSAKeyBytes eddsaX of       CryptoFailed err -> Left $ "Failed to create Ed25519 public key: " <> Text.pack (show err)       CryptoPassed res -> pure res-    sig <- case Ed25519.signature sig of+    sig <- case Ed25519.signature (Cose.unSignature sig) of       CryptoFailed err -> Left $ "Failed to create Ed25519 signature: " <> Text.pack (show err)       CryptoPassed res -> pure res-    if Ed25519.verify key msg sig+    if Ed25519.verify key (Cose.unMessage msg) sig       then Right ()       else Left "EdDSA Signature invalid" verify@@ -124,14 +126,14 @@     -- > For COSEAlgorithmIdentifier -7 (ES256), and other ECDSA-based algorithms,     -- the `sig` value MUST be encoded as an ASN.1 DER Ecdsa-Sig-Value, as defined     -- in [RFC3279](https://www.w3.org/TR/webauthn-2/#biblio-rfc3279) section 2.2.3.-    sig <- case ASN1.decodeASN1' ASN1.DER sig of+    sig <- case ASN1.decodeASN1' ASN1.DER (Cose.unSignature sig) of       Left err -> Left $ "Failed to decode ECDSA DER value: " <> Text.pack (show err)       -- Ecdsa-Sig-Value in https://datatracker.ietf.org/doc/html/rfc3279#section-2.2.3       Right [ASN1.Start ASN1.Sequence, ASN1.IntVal r, ASN1.IntVal s, ASN1.End ASN1.Sequence] ->         pure $ ECDSA.Signature r s       Right asns -> Left $ "Unexpected ECDSA ASN.1 structure: " <> Text.pack (show asns) -    if ECDSA.verify hash key sig msg+    if ECDSA.verify hash key sig (Cose.unMessage msg)       then Right ()       else Left "ECDSA Signature invalid" verify@@ -153,7 +155,7 @@               public_n = rsaN,               public_e = rsaE             }-    if RSA.verify (Just hash) key msg sig+    if RSA.verify (Just hash) key (Cose.unMessage msg) (Cose.unSignature sig)       then Right ()       else Left "RSA Signature invalid" verify key _ _ = error $ "PublicKeyWithSignAlg invariant violated for public key " <> show key <> ". This should not occur unless the PublicKeyWithSignAlg module has a bug"
src/Crypto/WebAuthn/Cose/PublicKey.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE StandaloneDeriving #-}  -- | Stability: experimental -- This module contains a partial implementation of the@@ -10,6 +11,7 @@     UncheckedPublicKey (..),     checkPublicKey,     PublicKey (PublicKey),+    EdDSAKeyBytes (..),      -- * COSE Elliptic Curves     CoseCurveEdDSA (..),@@ -24,15 +26,19 @@ import qualified Crypto.PubKey.ECC.Prim as ECC import qualified Crypto.PubKey.ECC.Types as ECC import qualified Crypto.PubKey.Ed25519 as Ed25519-import Crypto.WebAuthn.Internal.ToJSONOrphans ()+import Crypto.WebAuthn.Internal.ToJSONOrphans (PrettyHexByteString (PrettyHexByteString)) import Data.Aeson (ToJSON) import qualified Data.ByteString as BS-import qualified Data.ByteString.Base16 as Base16 import Data.Text (Text) import qualified Data.Text as Text-import qualified Data.Text.Encoding as Text import GHC.Generics (Generic) +-- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.2)+-- This contains the public key bytes.+newtype EdDSAKeyBytes = EdDSAKeyBytes {unEdDSAKeyBytes :: BS.ByteString}+  deriving newtype (Eq)+  deriving (Show, ToJSON) via PrettyHexByteString+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#credentialpublickey) -- A structured representation of a [COSE_Key](https://datatracker.ietf.org/doc/html/rfc8152#section-7) -- limited to what is know to be necessary for Webauthn public keys for the@@ -65,7 +71,7 @@         eddsaCurve :: CoseCurveEdDSA,         -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.2)         -- This contains the public key bytes.-        eddsaX :: BS.ByteString+        eddsaX :: EdDSAKeyBytes       }   | -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-2.1)     -- ECDSA Signature Algorithm@@ -113,13 +119,23 @@         -- GCD(e,\\lambda(n)) = 1, where \\lambda(n) = LCM(r_1 - 1, ..., r_u - 1)         rsaE :: Integer       }-  deriving (Eq, Show, Generic, ToJSON)+  deriving (Eq, Show, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON UncheckedPublicKey+ -- | Same as 'UncheckedPublicKey', but checked to be valid using -- 'checkPublicKey'. newtype PublicKey = CheckedPublicKey UncheckedPublicKey-  deriving newtype (Eq, Show, ToJSON)+  deriving newtype (Eq, Show) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving newtype instance ToJSON PublicKey+ -- | Returns the 'UncheckedPublicKey' for a t'PublicKey' pattern PublicKey :: UncheckedPublicKey -> PublicKey pattern PublicKey k <- CheckedPublicKey k@@ -139,9 +155,9 @@           <> " bytes, it has "           <> Text.pack (show actualSize)           <> " bytes instead: "-          <> Text.decodeUtf8 (Base16.encode eddsaX)+          <> Text.pack (show eddsaX)   where-    actualSize = BS.length eddsaX+    actualSize = BS.length $ unEdDSAKeyBytes eddsaX     expectedSize = coordinateSizeEdDSA eddsaCurve checkPublicKey key@PublicKeyECDSA {..}   | ECC.isPointValid curve point = Right $ CheckedPublicKey key@@ -161,8 +177,13 @@   = -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.1)     -- Ed25519 for use w/ EdDSA only     CoseCurveEd25519-  deriving (Eq, Show, Enum, Bounded, Generic, ToJSON)+  deriving (Eq, Show, Enum, Bounded, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON CoseCurveEdDSA+ -- | Returns the size of a coordinate point for a specific EdDSA curve in bytes. coordinateSizeEdDSA :: CoseCurveEdDSA -> Int coordinateSizeEdDSA CoseCurveEd25519 = Ed25519.publicKeySize@@ -178,7 +199,12 @@   | -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.1)     -- NIST P-521 also known as secp521r1     CoseCurveP521-  deriving (Eq, Show, Enum, Bounded, Generic, ToJSON)+  deriving (Eq, Show, Enum, Bounded, Generic)++-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON CoseCurveECDSA  -- | Converts a 'Cose.CoseCurveECDSA' to an 'ECC.CurveName'. The inverse -- function is 'fromCryptCurveECDSA'
src/Crypto/WebAuthn/Cose/PublicKeyWithSignAlg.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeSynonymInstances #-}  -- | Stability: experimental@@ -11,6 +12,8 @@     PublicKeyWithSignAlg (PublicKeyWithSignAlg, Crypto.WebAuthn.Cose.PublicKeyWithSignAlg.publicKey, signAlg),     CosePublicKey,     makePublicKeyWithSignAlg,+    Message (..),+    Signature (..),   ) where @@ -22,7 +25,8 @@ import qualified Crypto.WebAuthn.Cose.Internal.Registry as R import qualified Crypto.WebAuthn.Cose.PublicKey as P import qualified Crypto.WebAuthn.Cose.SignAlg as A-import Crypto.WebAuthn.Internal.ToJSONOrphans ()+import Crypto.WebAuthn.Internal.ToJSONOrphans (PrettyHexByteString (PrettyHexByteString))+import Data.Aeson (ToJSON) import qualified Data.Aeson as Aeson import qualified Data.ByteString as BS import Data.Functor (($>))@@ -43,8 +47,13 @@     -- acdCredentialPublicKeyBytes. This would then require parametrizing     -- 'PublicKeyWithSignAlg' with 'raw :: Bool'   }-  deriving (Eq, Show, Generic, Aeson.ToJSON)+  deriving (Eq, Show, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance Aeson.ToJSON PublicKeyWithSignAlg+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#credentialpublickey) -- A structured and checked representation of a -- [COSE_Key](https://datatracker.ietf.org/doc/html/rfc8152#section-7), limited@@ -53,8 +62,21 @@ -- field. type CosePublicKey = PublicKeyWithSignAlg +-- | A wrapper for the bytes of a message that should be verified.+-- This is used for both assertion and assertion.+newtype Message = Message {unMessage :: BS.ByteString}+  deriving newtype (Eq, Show)+  deriving (ToJSON) via PrettyHexByteString++-- | [(spec)](https://www.w3.org/TR/webauthn-2/#sctn-signature-attestation-types)+-- A wrapper for the bytes of a signature that can be used to verify a 'Message'.+-- The encoding is specific to webauthn and depends on the 'A.CoseSignAlg' used.+newtype Signature = Signature {unSignature :: BS.ByteString}+  deriving newtype (Eq, Show)+  deriving (ToJSON) via PrettyHexByteString+ -- | Deconstructs a 'makePublicKeyWithSignAlg' into its t'P.PublicKey' and--- 'A.CoseSignAlg'. Since 'makePublicKeyWithSignAlg' can only be constructed+-- 'A.CoseSignAlg'. Since t'PublicKeyWithSignAlg' can only be constructed -- using 'makePublicKeyWithSignAlg', we can be sure that the signature scheme -- of t'P.PublicKey' and 'A.CoseSignAlg' matches. pattern PublicKeyWithSignAlg :: P.PublicKey -> A.CoseSignAlg -> PublicKeyWithSignAlg@@ -90,7 +112,7 @@         <> encode R.CoseKeyTypeParameterOKPCrv         <> encode (fromCurveEdDSA eddsaCurve)         <> encode R.CoseKeyTypeParameterOKPX-        <> encodeBytes eddsaX+        <> encodeBytes (P.unEdDSAKeyBytes eddsaX)     P.PublicKey P.PublicKeyECDSA {..} ->       common R.CoseKeyTypeEC2         <> encode R.CoseKeyTypeParameterEC2Crv@@ -195,7 +217,7 @@             decodeExpected R.CoseKeyTypeParameterOKPCrv             eddsaCurve <- toCurveEdDSA <$> decode             decodeExpected R.CoseKeyTypeParameterOKPX-            eddsaX <- decodeBytesCanonical+            eddsaX <- P.EdDSAKeyBytes <$> decodeBytesCanonical             pure P.PublicKeyEdDSA {..}            decodeECDSAKey :: Decoder s P.UncheckedPublicKey
src/Crypto/WebAuthn/Cose/SignAlg.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE StandaloneDeriving #-}  -- | Stability: experimental -- This module contains definitions for [COSE registry](https://www.iana.org/assignments/cose/cose.xhtml)@@ -95,8 +96,13 @@     --     -- Security considerations are [here](https://www.rfc-editor.org/rfc/rfc8812.html#section-5)     CoseSignAlgRSA CoseHashAlgRSA-  deriving (Eq, Show, Ord, Generic, ToJSON)+  deriving (Eq, Show, Ord, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON CoseSignAlg+ -- | Hash algorithms that can be used with the ECDSA signature algorithm data CoseHashAlgECDSA   = -- | SHA-256@@ -105,8 +111,13 @@     CoseHashAlgECDSASHA384   | -- | SHA-512     CoseHashAlgECDSASHA512-  deriving (Eq, Show, Ord, Enum, Bounded, Generic, ToJSON)+  deriving (Eq, Show, Ord, Enum, Bounded, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON CoseHashAlgECDSA+ -- | Hash algorithms that can be used with the RSA signature algorithm data CoseHashAlgRSA   = -- | SHA-1 (deprecated)@@ -117,7 +128,12 @@     CoseHashAlgRSASHA384   | -- | SHA-512     CoseHashAlgRSASHA512-  deriving (Eq, Show, Ord, Enum, Bounded, Generic, ToJSON)+  deriving (Eq, Show, Ord, Enum, Bounded, Generic)++-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON CoseHashAlgRSA  -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-2.2) -- [Cose Algorithm registry](https://www.iana.org/assignments/cose/cose.xhtml#algorithms)
src/Crypto/WebAuthn/Internal/ToJSONOrphans.hs view
@@ -3,7 +3,7 @@  -- | Stability: internal -- This module contain some useful orphan 'ToJSON' instances for pretty-printing values from third-party libraries-module Crypto.WebAuthn.Internal.ToJSONOrphans () where+module Crypto.WebAuthn.Internal.ToJSONOrphans (PrettyHexByteString (..)) where  import Crypto.Hash (Digest) import qualified Crypto.PubKey.ECC.Types as ECC@@ -23,9 +23,17 @@ import qualified Data.X509 as X509 import qualified Data.X509.Validation as X509 -instance ToJSON BS.ByteString where-  toJSON = String . Text.decodeUtf8 . Base16.encode+-- | This type holds a bytestring and has no restrictions to its contents. Its main purpose is to simplify debugging:+-- its 'Aeson.ToJSON' and 'Show' instances convert it to base16 (hexadecimal).+newtype PrettyHexByteString = PrettyHexByteString BS.ByteString+  deriving newtype (Eq) +instance ToJSON PrettyHexByteString where+  toJSON (PrettyHexByteString bytes) = String . Text.decodeUtf8 . Base16.encode $ bytes++instance Show PrettyHexByteString where+  show (PrettyHexByteString bytes) = Text.unpack . Text.decodeUtf8 . Base16.encode $ bytes+ instance ToJSON (Digest h) where   toJSON = String . Text.decodeUtf8 . Base16.encode . convert @@ -55,7 +63,7 @@   toJSON X509.ExtensionRaw {..} =     object       [ "extRawOID" .= oidToJSON extRawOID,-        "extRawContent" .= extRawContent+        "extRawContent" .= PrettyHexByteString extRawContent       ]  instance ToJSON ECC.CurveName where
src/Crypto/WebAuthn/Metadata/Service/Types.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE KindSignatures #-}+{-# LANGUAGE StandaloneDeriving #-}  -- | Stability: experimental -- This module contains additional Haskell-specific type definitions for the@@ -87,8 +88,13 @@     -- rogueListURL, rogueListHash. TODO, but not currently used in the     -- BLOB and difficult to implement since it involves JWT   }-  deriving (Eq, Show, Generic, ToJSON)+  deriving (Eq, Show, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON (MetadataEntry p)+ -- | Same as 'MetadataEntry', but with its type parameter erased data SomeMetadataEntry = forall p. SingI p => SomeMetadataEntry (MetadataEntry p) @@ -114,4 +120,9 @@     -- | [(spec)](https://fidoalliance.org/specs/mds/fido-metadata-service-v3.0-ps-20210518.html#dom-statusreport-certificationrequirementsversion)     srCertificationRequirementsVersion :: Maybe Text   }-  deriving (Eq, Show, Generic, ToJSON)+  deriving (Eq, Show, Generic)++-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON StatusReport
src/Crypto/WebAuthn/Metadata/Statement/Decode.hs view
@@ -23,7 +23,6 @@ import qualified Crypto.WebAuthn.Model as M import Crypto.WebAuthn.Model.Identifier (AAGUID (AAGUID), AuthenticatorIdentifier (AuthenticatorIdentifierFido2, AuthenticatorIdentifierFidoU2F), SubjectKeyIdentifier (SubjectKeyIdentifier)) import Data.Bifunctor (first)-import qualified Data.ByteString as BS import qualified Data.ByteString.Base16 as Base16 import qualified Data.ByteString.Base64 as Base64 import Data.List.NonEmpty (NonEmpty)@@ -117,10 +116,10 @@         transform _ = Nothing      -- Decodes the PNG bytes of an [icon](https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.0-ps-20210518.html#dom-metadatastatement-icon) field of a metadata statement-    decodeIcon :: IDL.DOMString -> Either Text BS.ByteString+    decodeIcon :: IDL.DOMString -> Either Text StatementTypes.PNGBytes     decodeIcon dataUrl = case Text.stripPrefix "data:image/png;base64," dataUrl of       Nothing -> Left $ "Icon decoding failed because there is no \"data:image/png;base64,\" prefix: " <> dataUrl       Just suffix ->         -- TODO: Use non-lenient decoding, it's only needed because of a spec violation,         -- see <https://github.com/tweag/haskell-fido2/issues/68>-        Right $ Base64.decodeLenient (encodeUtf8 suffix)+        Right $ StatementTypes.PNGBytes $ Base64.decodeLenient (encodeUtf8 suffix)
src/Crypto/WebAuthn/Metadata/Statement/Types.hs view
@@ -1,13 +1,17 @@+{-# LANGUAGE StandaloneDeriving #-}+ -- | Stability: experimental -- This module contains additional Haskell-specific type definitions for the -- [FIDO Metadata Statement](https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.0-ps-20210518.html) -- specification module Crypto.WebAuthn.Metadata.Statement.Types   ( MetadataStatement (..),+    PNGBytes (..),     WebauthnAttestationType (..),   ) where +import Crypto.WebAuthn.Internal.ToJSONOrphans (PrettyHexByteString (PrettyHexByteString)) import qualified Crypto.WebAuthn.Metadata.FidoRegistry as Registry import qualified Crypto.WebAuthn.Metadata.Statement.WebIDL as StatementIDL import qualified Crypto.WebAuthn.Metadata.UAF as UAF@@ -68,16 +72,31 @@     -- msEcdaaTrustAnchors, not needed for the subset we implement, FIDO 2 and FIDO U2F      -- | [(spec)](https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.0-ps-20210518.html#dom-metadatastatement-icon)-    msIcon :: Maybe BS.ByteString,+    msIcon :: Maybe PNGBytes,     -- | [(spec)](https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.0-ps-20210518.html#dom-metadatastatement-supportedextensions)     msSupportedExtensions :: Maybe (NonEmpty StatementIDL.ExtensionDescriptor),     -- | [(spec)](https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.0-ps-20210518.html#dom-metadatastatement-authenticatorgetinfo)     msAuthenticatorGetInfo :: Maybe StatementIDL.AuthenticatorGetInfo   }-  deriving (Eq, Show, Generic, ToJSON)+  deriving (Eq, Show, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON MetadataStatement++-- | A wrapper for the bytes of a PNG images.+newtype PNGBytes = PNGBytes {unPNGBytes :: BS.ByteString}+  deriving newtype (Eq)+  deriving (Show, ToJSON) via PrettyHexByteString+ -- | Values of 'Registry.AuthenticatorAttestationType' but limited to the ones possible with Webauthn, see https://www.w3.org/TR/webauthn-2/#sctn-attestation-types data WebauthnAttestationType   = WebauthnAttestationBasic   | WebauthnAttestationAttCA-  deriving (Eq, Show, Generic, ToJSON)+  deriving (Eq, Show, Generic)++-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON WebauthnAttestationType
src/Crypto/WebAuthn/Model/Identifier.hs view
@@ -25,8 +25,13 @@ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#aaguid) newtype AAGUID = AAGUID {unAAGUID :: UUID}   deriving (Eq, Show)-  deriving newtype (Hashable, ToJSON)+  deriving newtype (Hashable) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving newtype instance ToJSON AAGUID+ -- | A way to identify an authenticator data AuthenticatorIdentifier (p :: M.ProtocolKind) where   -- | [(spec)](https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.0-ps-20210518.html#dom-metadatastatement-aaguid)@@ -51,6 +56,9 @@  deriving instance Eq (AuthenticatorIdentifier p) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules instance ToJSON (AuthenticatorIdentifier p) where   toJSON (AuthenticatorIdentifierFido2 aaguid) =     object@@ -70,8 +78,10 @@ newtype SubjectKeyIdentifier = SubjectKeyIdentifier {unSubjectKeyIdentifier :: Digest SHA1}   deriving (Eq, Show) -instance ToJSON SubjectKeyIdentifier where-  toJSON = toJSON @BS.ByteString . convert . unSubjectKeyIdentifier+-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving newtype instance ToJSON SubjectKeyIdentifier  instance Hashable SubjectKeyIdentifier where   hashWithSalt = hashUsing @BS.ByteString (convert . unSubjectKeyIdentifier)
src/Crypto/WebAuthn/Model/Kinds.hs view
@@ -79,6 +79,9 @@  deriving instance Eq (SCeremonyKind c) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules instance ToJSON (SCeremonyKind c) where   toJSON SRegistration = "Registration"   toJSON SAuthentication = "Authentication"@@ -109,6 +112,9 @@  deriving instance Eq (SProtocolKind p) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules instance ToJSON (SProtocolKind p) where   toJSON SFidoU2F = "FidoU2F"   toJSON SFido2 = "Fido2"
src/Crypto/WebAuthn/Model/Types.hs view
@@ -29,9 +29,9 @@ --   the initials of the constructor name. -- * Every type should have a 'ToJSON' instance for pretty-printing purposes. --   This JSON encoding doesn't correspond to any encoding used for---   sending/receiving these structures, it's only used for pretty-printing,+--   sending\/receiving these structures, it's only used for pretty-printing, --   which is why it doesn't need to be standardized. For encoding these---   structures from/to JSON for sending/receiving, see the+--   structures from\/to JSON for sending/receiving, see the --   'Crypto.WebAuthn.Model.WebIDL' module -- #defaultFields# -- * Fields of the WebAuthn standard that are optional (for writing) but have@@ -128,7 +128,7 @@ import Crypto.Random (MonadRandom, getRandomBytes) import qualified Crypto.WebAuthn.Cose.PublicKeyWithSignAlg as Cose import qualified Crypto.WebAuthn.Cose.SignAlg as Cose-import Crypto.WebAuthn.Internal.ToJSONOrphans ()+import Crypto.WebAuthn.Internal.ToJSONOrphans (PrettyHexByteString (PrettyHexByteString)) import Crypto.WebAuthn.Model.Identifier (AAGUID) import Crypto.WebAuthn.Model.Kinds   ( AttestationKind (Unverifiable, Verifiable),@@ -162,9 +162,12 @@  deriving instance Show (RawField raw) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules instance ToJSON (RawField raw) where   toJSON NoRaw = "<none>"-  toJSON (WithRaw bytes) = toJSON bytes+  toJSON (WithRaw bytes) = toJSON $ PrettyHexByteString bytes  -- | [(spec)](https://www.w3.org/TR/webauthn-2/#enumdef-publickeycredentialtype) -- This enumeration defines the valid credential types. It is an extension point;@@ -177,6 +180,9 @@ data CredentialType = CredentialTypePublicKey   deriving (Eq, Show, Bounded, Enum, Ord, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules instance ToJSON CredentialType where   toJSON CredentialTypePublicKey = "CredentialTypePublicKey" @@ -220,8 +226,13 @@     -- stored. Draft version 3 of the standard [fixes     -- this](https://github.com/w3c/webauthn/pull/1654).     AuthenticatorTransportUnknown Text-  deriving (Eq, Show, Ord, Generic, ToJSON)+  deriving (Eq, Show, Ord, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON AuthenticatorTransport+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#enumdef-authenticatorattachment) -- This enumeration’s values describe [authenticators](https://www.w3.org/TR/webauthn-2/#authenticator)' -- [attachment modalities](https://www.w3.org/TR/webauthn-2/#authenticator-attachment-modality).@@ -239,8 +250,13 @@   | -- | [(spec)](https://www.w3.org/TR/webauthn-2/#dom-authenticatorattachment-cross-platform)     -- This value indicates [cross-platform attachment](https://www.w3.org/TR/webauthn-2/#cross-platform-attachment).     AuthenticatorAttachmentCrossPlatform-  deriving (Eq, Show, Bounded, Enum, Ord, Generic, ToJSON)+  deriving (Eq, Show, Bounded, Enum, Ord, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON AuthenticatorAttachment+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#enumdef-residentkeyrequirement) -- This enumeration’s values describe the [Relying Party](https://www.w3.org/TR/webauthn-2/#relying-party)'s -- requirements for [client-side discoverable credentials](https://www.w3.org/TR/webauthn-2/#client-side-discoverable-credential)@@ -269,8 +285,13 @@     -- and is prepared to receive an error if a     -- [client-side discoverable credential](https://www.w3.org/TR/webauthn-2/#client-side-discoverable-credential) cannot be created.     ResidentKeyRequirementRequired-  deriving (Eq, Show, Bounded, Enum, Ord, Generic, ToJSON)+  deriving (Eq, Show, Bounded, Enum, Ord, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON ResidentKeyRequirement+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#enum-userVerificationRequirement) -- A [WebAuthn Relying Party](https://www.w3.org/TR/webauthn-2/#webauthn-relying-party) may -- require [user verification](https://www.w3.org/TR/webauthn-2/#user-verification) for some@@ -296,8 +317,13 @@     -- does not want [user verification](https://www.w3.org/TR/webauthn-2/#user-verification) employed     -- during the operation (e.g., in the interest of minimizing disruption to the user interaction flow).     UserVerificationRequirementDiscouraged-  deriving (Eq, Show, Bounded, Enum, Ord, Generic, ToJSON)+  deriving (Eq, Show, Bounded, Enum, Ord, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON UserVerificationRequirement+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#enum-attestation-convey) -- [WebAuthn Relying Parties](https://www.w3.org/TR/webauthn-2/#webauthn-relying-party) may use -- [AttestationConveyancePreference](https://www.w3.org/TR/webauthn-2/#enumdef-attestationconveyancepreference)@@ -352,8 +378,13 @@     -- and [attestation statement](https://www.w3.org/TR/webauthn-2/#attestation-statement), unaltered,     -- to the [Relying Party](https://www.w3.org/TR/webauthn-2/#relying-party).     AttestationConveyancePreferenceEnterprise-  deriving (Eq, Show, Bounded, Enum, Ord, Generic, ToJSON)+  deriving (Eq, Show, Bounded, Enum, Ord, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON AttestationConveyancePreference+ -- | An X.509 certificate chain that can be used to verify an attestation -- statement data AttestationChain (p :: ProtocolKind) where@@ -367,6 +398,9 @@  deriving instance Show (AttestationChain p) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules instance ToJSON (AttestationChain p) where   toJSON (Fido2Chain chain) = toJSON chain   toJSON (FidoU2FCert cert) = toJSON [cert]@@ -423,8 +457,13 @@     -- presented to [Relying Parties](https://www.w3.org/TR/webauthn-2/#relying-party)     -- do not provide uniquely identifiable information, e.g., that might be used for tracking purposes.     VerifiableAttestationTypeAnonCA-  deriving (Eq, Show, Bounded, Enum, Ord, Generic, ToJSON)+  deriving (Eq, Show, Bounded, Enum, Ord, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON VerifiableAttestationType+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#sctn-attestation-types) -- WebAuthn supports several [attestation types](https://www.w3.org/TR/webauthn-2/#attestation-type), -- defining the semantics of [attestation statements](https://www.w3.org/TR/webauthn-2/#attestation-statement)@@ -458,6 +497,9 @@  deriving instance Show (AttestationType k) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules instance ToJSON (AttestationType k) where   toJSON AttestationTypeNone =     object@@ -496,8 +538,13 @@ -- uses DOMString, while the latter uses USVString. Is this a bug in the spec or is there an actual difference? newtype RpId = RpId {unRpId :: Text}   deriving (Eq, Show, Ord)-  deriving newtype (IsString, ToJSON)+  deriving newtype (IsString) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving newtype instance ToJSON RpId+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialentity-name) -- A [human-palatable](https://www.w3.org/TR/webauthn-2/#human-palatability) -- identifier for the [Relying Party](https://www.w3.org/TR/webauthn-2/#relying-party),@@ -512,8 +559,13 @@ -- about how this metadata is encoded. newtype RelyingPartyName = RelyingPartyName {unRelyingPartyName :: Text}   deriving (Eq, Show)-  deriving newtype (IsString, ToJSON)+  deriving newtype (IsString) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving newtype instance ToJSON RelyingPartyName+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#user-handle) -- The user handle is specified by a [Relying Party](https://www.w3.org/TR/webauthn-2/#relying-party), -- as the value of 'id', and used to [map](https://www.w3.org/TR/webauthn-2/#authenticator-credentials-map)@@ -525,8 +577,12 @@ -- with a maximum size of 64 bytes, and is not meant to be displayed to the user. newtype UserHandle = UserHandle {unUserHandle :: BS.ByteString}   deriving (Eq, Show, Ord)-  deriving newtype (ToJSON) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving via PrettyHexByteString instance ToJSON UserHandle+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#user-handle) -- A user handle is an opaque [byte sequence](https://infra.spec.whatwg.org/#byte-sequence) -- with a maximum size of 64 bytes, and is not meant to be displayed to the user.@@ -547,8 +603,13 @@ -- about how this metadata is encoded. newtype UserAccountDisplayName = UserAccountDisplayName {unUserAccountDisplayName :: Text}   deriving (Eq, Show)-  deriving newtype (IsString, ToJSON)+  deriving newtype (IsString) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving newtype instance ToJSON UserAccountDisplayName+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialentity-name) -- A [human-palatable](https://www.w3.org/TR/webauthn-2/#human-palatability) identifier for a user account. -- It is intended only for display, i.e., aiding the user in determining the difference between user accounts with@@ -566,16 +627,25 @@ --   about how this metadata is encoded. newtype UserAccountName = UserAccountName {unUserAccountName :: Text}   deriving (Eq, Show)-  deriving newtype (IsString, ToJSON)+  deriving newtype (IsString) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving newtype instance ToJSON UserAccountName+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#credential-id) -- A probabilistically-unique [byte sequence](https://infra.spec.whatwg.org/#byte-sequence) -- identifying a [public key credential](https://www.w3.org/TR/webauthn-2/#public-key-credential-source) -- source and its [authentication assertions](https://www.w3.org/TR/webauthn-2/#authentication-assertion). newtype CredentialId = CredentialId {unCredentialId :: BS.ByteString}   deriving (Eq, Show, Ord)-  deriving newtype (ToJSON) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving via PrettyHexByteString instance ToJSON CredentialId+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#credential-id) -- Generates a random 'CredentialId' using 16 random bytes. -- This is only useful for authenticators, not for relying parties.@@ -589,8 +659,12 @@ -- security consideration. newtype Challenge = Challenge {unChallenge :: BS.ByteString}   deriving (Eq, Show, Ord)-  deriving newtype (ToJSON) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving via PrettyHexByteString instance ToJSON Challenge+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#sctn-cryptographic-challenges) -- In order to prevent replay attacks, the challenges MUST contain enough entropy -- to make guessing them infeasible. Challenges SHOULD therefore be at least 16 bytes long.@@ -602,8 +676,12 @@ -- This is treated as a hint, and MAY be overridden by the [client](https://www.w3.org/TR/webauthn-2/#client). newtype Timeout = Timeout {unTimeout :: Word32}   deriving (Eq, Show)-  deriving newtype (ToJSON) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving newtype instance ToJSON Timeout+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#assertion-signature) -- An assertion signature is produced when the -- [authenticatorGetAssertion](https://www.w3.org/TR/webauthn-2/#authenticatorgetassertion)@@ -624,39 +702,65 @@ -- format is illustrated in [Figure 4, below](https://www.w3.org/TR/webauthn-2/#fig-signature). newtype AssertionSignature = AssertionSignature {unAssertionSignature :: BS.ByteString}   deriving (Eq, Show)-  deriving newtype (ToJSON) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving via PrettyHexByteString instance ToJSON AssertionSignature+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#rpidhash) -- SHA-256 hash of the [RP ID](https://www.w3.org/TR/webauthn-2/#rp-id) the -- [credential](https://www.w3.org/TR/webauthn-2/#public-key-credential) is -- [scoped](https://www.w3.org/TR/webauthn-2/#scope) to. newtype RpIdHash = RpIdHash {unRpIdHash :: Digest SHA256}   deriving (Eq, Show)-  deriving newtype (ToJSON) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving newtype instance ToJSON RpIdHash+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#collectedclientdata-hash-of-the-serialized-client-data) -- This is the hash (computed using SHA-256) of the [JSON-compatible serialization of client data](https://www.w3.org/TR/webauthn-2/#collectedclientdata-json-compatible-serialization-of-client-data), -- as constructed by the client. newtype ClientDataHash = ClientDataHash {unClientDataHash :: Digest SHA256}   deriving (Eq, Show)-  deriving newtype (ToJSON) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving newtype instance ToJSON ClientDataHash+ -- | [(spec)](https://html.spec.whatwg.org/multipage/origin.html#concept-origin) newtype Origin = Origin {unOrigin :: Text}   deriving (Eq, Show)-  deriving newtype (IsString, ToJSON)+  deriving newtype (IsString) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving newtype instance ToJSON Origin+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#signcount) -- [Signature counter](https://www.w3.org/TR/webauthn-2/#signature-counter) newtype SignatureCounter = SignatureCounter {unSignatureCounter :: Word32}   deriving (Eq, Show)-  deriving newtype (Num, Ord, ToJSON)+  deriving newtype (Num, Ord) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving newtype instance ToJSON SignatureCounter+ -- | The encoding of a 'Cose.CosePublicKey' newtype PublicKeyBytes = PublicKeyBytes {unPublicKeyBytes :: BS.ByteString}   deriving (Eq, Show)-  deriving newtype (ToJSON) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving via PrettyHexByteString instance ToJSON PublicKeyBytes+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#iface-authentication-extensions-client-inputs) -- This is a dictionary containing the [client extension input](https://www.w3.org/TR/webauthn-2/#client-extension-input) -- values for zero or more [WebAuthn Extensions](https://www.w3.org/TR/webauthn-2/#webauthn-extensions).@@ -701,6 +805,9 @@   }   deriving (Eq, Show) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules instance ToJSON AuthenticatorExtensionOutputs where   toJSON _ = object [] @@ -718,8 +825,13 @@     -- intended only for display. For example, "ACME Corporation", "Wonderful Widgets, Inc." or "ОАО Примертех".     creName :: RelyingPartyName   }-  deriving (Eq, Show, Generic, ToJSON)+  deriving (Eq, Show, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON CredentialRpEntity+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#dictionary-user-credential-params) -- The 'CredentialUserEntity' dictionary is used to supply additional -- user account attributes when creating a new credential.@@ -746,8 +858,13 @@     -- accounts with similar 'cueDisplayName's. For example, "alexm", "alex.mueller@example.com" or "+14255551234".     cueName :: UserAccountName   }-  deriving (Eq, Show, Generic, ToJSON)+  deriving (Eq, Show, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON CredentialUserEntity+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#dictionary-credential-params) -- This dictionary is used to supply additional parameters when creating a new credential. data CredentialParameters = CredentialParameters@@ -760,8 +877,13 @@     -- key pair to be generated, e.g., RSA or Elliptic Curve.     cpAlg :: Cose.CoseSignAlg   }-  deriving (Eq, Show, Generic, ToJSON)+  deriving (Eq, Show, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON CredentialParameters+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#dictdef-publickeycredentialdescriptor) -- This dictionary contains the attributes that are specified by a caller when referring to a -- [public key credential](https://www.w3.org/TR/webauthn-2/#public-key-credential) as an input parameter to the@@ -782,8 +904,13 @@     -- of the [public key credential](https://www.w3.org/TR/webauthn-2/#public-key-credential) the caller is referring to.     cdTransports :: Maybe [AuthenticatorTransport]   }-  deriving (Eq, Show, Generic, ToJSON)+  deriving (Eq, Show, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON CredentialDescriptor+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#dictdef-authenticatorselectioncriteria) -- [WebAuthn Relying Parties](https://www.w3.org/TR/webauthn-2/#webauthn-relying-party) -- may use the 'AuthenticatorSelectionCriteria' dictionary to specify their@@ -808,8 +935,13 @@     -- The default value of this field is 'Crypto.WebAuthn.Model.Defaults.ascUserVerificationDefault'.     ascUserVerification :: UserVerificationRequirement   }-  deriving (Eq, Show, Generic, ToJSON)+  deriving (Eq, Show, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON AuthenticatorSelectionCriteria+ -- | [(spec)](https://www.w3.org/TR/webauthn-2/#flags) data AuthenticatorDataFlags = AuthenticatorDataFlags   { -- | [(spec)](https://www.w3.org/TR/webauthn-2/#concept-user-present)@@ -821,8 +953,13 @@     -- the user is said to be "[verified](https://www.w3.org/TR/webauthn-2/#concept-user-verified)".     adfUserVerified :: Bool   }-  deriving (Eq, Show, Generic, ToJSON)+  deriving (Eq, Show, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON AuthenticatorDataFlags+ -- | A type encompassing the credential options, both for -- [creation](https://www.w3.org/TR/webauthn-2/#dictionary-makecredentialoptions) -- and@@ -954,6 +1091,9 @@  deriving instance Show (CredentialOptions c) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules instance ToJSON (CredentialOptions c) where   toJSON CredentialOptionsRegistration {..} =     object@@ -1027,6 +1167,9 @@   }   deriving (Eq, Show) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules instance SingI c => ToJSON (CollectedClientData (c :: CeremonyKind) raw) where   toJSON CollectedClientData {..} =     object@@ -1061,6 +1204,9 @@  deriving instance Show (AttestedCredentialData c raw) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules instance ToJSON (AttestedCredentialData c raw) where   toJSON AttestedCredentialData {..} =     object@@ -1122,8 +1268,13 @@     -- | Raw encoded data for verification purposes     adRawData :: RawField raw   }-  deriving (Eq, Show, Generic, ToJSON)+  deriving (Eq, Show, Generic) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON (AuthenticatorData c raw)+ -- | The result from verifying an attestation statement. -- Either the result is verifiable, in which case @k ~ 'Verifiable'@, the -- 'AttestationType' contains a verifiable certificate chain.@@ -1344,6 +1495,9 @@  deriving instance Show (AttestationObject raw) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules instance ToJSON (AttestationObject raw) where   toJSON AttestationObject {..} =     object@@ -1446,6 +1600,9 @@  deriving instance Show (AuthenticatorResponse c raw) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules instance ToJSON (AuthenticatorResponse c raw) where   toJSON AuthenticatorResponseRegistration {..} =     object@@ -1504,4 +1661,9 @@     -- by the extension’s [client extension processing](https://www.w3.org/TR/webauthn-2/#client-extension-processing).     cClientExtensionResults :: AuthenticationExtensionsClientOutputs   }-  deriving (Eq, Show, Generic, ToJSON)+  deriving (Eq, Show, Generic)++-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON (Credential c raw)
src/Crypto/WebAuthn/Operation/Authentication.hs view
@@ -348,11 +348,11 @@   -- 20. Using credentialPublicKey, verify that sig is a valid signature over   -- the binary concatenation of authData and hash.   let pubKeyBytes = LBS.fromStrict $ M.unPublicKeyBytes $ cePublicKeyBytes entry-      message = rawData <> convert (M.unClientDataHash hash)+      message = Cose.Message $ rawData <> convert (M.unClientDataHash hash)   case CBOR.deserialiseFromBytes decode pubKeyBytes of     Left err -> failure $ AuthenticationSignatureDecodingError err     Right (_, coseKey) ->-      case Cose.verify coseKey message (M.unAssertionSignature sig) of+      case Cose.verify coseKey message (Cose.Signature $ M.unAssertionSignature sig) of         Right () -> pure ()         Left err -> failure $ AuthenticationSignatureInvalid err 
src/Crypto/WebAuthn/Operation/CredentialEntry.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE StandaloneDeriving #-}+ -- | Stability: experimental -- This module represents all the information the Relying Party must store in -- the database for every credential.@@ -19,4 +21,9 @@     ceSignCounter :: M.SignatureCounter,     ceTransports :: [M.AuthenticatorTransport]   }-  deriving (Eq, Show, Generic, ToJSON)+  deriving (Eq, Show, Generic)++-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON CredentialEntry
src/Crypto/WebAuthn/Operation/Registration.hs view
@@ -186,6 +186,9 @@  deriving instance Eq (AuthenticatorModel k) +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules instance ToJSON (AuthenticatorModel k) where   toJSON UnknownAuthenticator =     object@@ -234,6 +237,9 @@  deriving instance Show SomeAttestationStatement +-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules instance ToJSON SomeAttestationStatement where   toJSON SomeAttestationStatement {..} =     object@@ -250,7 +256,12 @@     -- | Information about the attestation statement     rrAttestationStatement :: SomeAttestationStatement   }-  deriving (Show, Generic, ToJSON)+  deriving (Show, Generic)++-- | An arbitrary and potentially unstable JSON encoding, only intended for+-- logging purposes. To actually encode and decode structures, use the+-- "Crypto.WebAuthn.Encoding" modules+deriving instance ToJSON RegistrationResult  -- | [(spec)](https://www.w3.org/TR/webauthn-2/#sctn-registering-a-new-credential) -- The resulting 'rrEntry' of this call should be stored in a database by the
tests/PublicKeySpec.hs view
@@ -40,7 +40,7 @@ prop_signverify seed Key.KeyPair {..} msg = do   let signAlg = Cose.signAlg cosePubKey       sig = runSeededMonadRandom seed $ Key.sign signAlg privKey msg-      valid = Cose.verify cosePubKey msg sig+      valid = Cose.verify cosePubKey (Cose.Message msg) (Cose.Signature sig)    in case valid of         Left _ -> False         Right () -> True
tests/Spec/Key.hs view
@@ -66,7 +66,7 @@       unchecked =         Cose.PublicKeyEdDSA           { eddsaCurve = Cose.CoseCurveEd25519,-            eddsaX = convert pubKey'+            eddsaX = Cose.EdDSAKeyBytes $ convert pubKey'           }       pubKey = fromRight (error "unreachable") $ Cose.checkPublicKey unchecked       cosePubKey = fromRight (error "unreachable") $ Cose.makePublicKeyWithSignAlg pubKey Cose.CoseSignAlgEdDSA@@ -157,8 +157,8 @@  toX509 :: Cose.UncheckedPublicKey -> X509.PubKey toX509 Cose.PublicKeyEdDSA {eddsaCurve = Cose.CoseCurveEd25519, ..} =-  let key = case Ed25519.publicKey eddsaX of-        CryptoFailed err -> error $ "Failed to create a cryptonite Ed25519 public key of a bytestring with size " <> show (BS.length eddsaX) <> ": " <> show err+  let key = case Ed25519.publicKey $ Cose.unEdDSAKeyBytes eddsaX of+        CryptoFailed err -> error $ "Failed to create a cryptonite Ed25519 public key of a bytestring with size " <> show (BS.length $ Cose.unEdDSAKeyBytes eddsaX) <> ": " <> show err         CryptoPassed res -> res    in X509.PubKeyEd25519 key toX509 Cose.PublicKeyECDSA {..} =
webauthn.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: webauthn-version: 0.7.0.0+version: 0.8.0.0 license: Apache-2.0 license-file: LICENSE copyright:@@ -69,15 +69,15 @@   import: sanity   hs-source-dirs: src   build-depends:-    base                  >= 4.13.0 && < 4.18,-    aeson                 >= 1.4.7 && < 2.2,+    base                  >= 4.13.0 && < 4.20,+    aeson                 >= 1.4.7 && < 2.3,     asn1-encoding         >= 0.9.6 && < 0.10,     asn1-parse            >= 0.9.5 && < 0.10,     asn1-types            >= 0.3.4 && < 0.4,     base16-bytestring     >= 1.0.0 && < 1.1,     base64-bytestring     >= 1.2.1 && < 1.3,     binary                >= 0.8.7 && < 0.9,-    bytestring            >= 0.10.10 && < 0.12,+    bytestring            >= 0.10.10 && < 0.13,     cborg                 >= 0.2.4 && < 0.3,     containers            >= 0.6.2 && < 0.7,     cryptonite            >= 0.27 && < 0.31,@@ -91,9 +91,9 @@     mtl                   >= 2.2.2 && < 2.4,     serialise             >= 0.2.3 && < 0.3,     singletons            >= 2.6 && < 3.2,-    text                  >= 1.2.4 && < 2.1,-    these                 >= 1.1 && < 1.2,-    time                  >= 1.9.3 && < 1.12,+    text                  >= 1.2.4 && < 2.2,+    these                 >= 1.1 && < 1.3,+    time                  >= 1.9.3 && < 1.14,     unordered-containers  >= 0.2.11 && < 0.3,     uuid                  >= 1.3.13 && < 1.4,     validation            >= 1.1 && < 1.3,