webauthn 0.5.0.0 → 0.5.0.1
raw patch · 15 files changed
+101/−81 lines, 15 filesdep ~basedep ~josedep ~lensPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: base, jose, lens, memory, mtl, text
API changes (from Hackage documentation)
- Crypto.WebAuthn.Encoding.Internal.WebAuthnJson: type family JSON a :: Type;
- Crypto.WebAuthn.Model.Types: type family AttStmtVerificationError a :: Type;
+ Crypto.WebAuthn.Encoding.Internal.WebAuthnJson: AuthenticationExtensionsClientInputs :: Maybe Bool -> AuthenticationExtensionsClientInputs
+ Crypto.WebAuthn.Encoding.Internal.WebAuthnJson: AuthenticationExtensionsClientOutputs :: Maybe CredentialPropertiesOutput -> AuthenticationExtensionsClientOutputs
+ Crypto.WebAuthn.Encoding.Internal.WebAuthnJson: CredentialPropertiesOutput :: Maybe Bool -> CredentialPropertiesOutput
+ Crypto.WebAuthn.Encoding.Internal.WebAuthnJson: [$sel:credProps:AuthenticationExtensionsClientInputs] :: AuthenticationExtensionsClientInputs -> Maybe Bool
+ Crypto.WebAuthn.Encoding.Internal.WebAuthnJson: [$sel:credProps:AuthenticationExtensionsClientOutputs] :: AuthenticationExtensionsClientOutputs -> Maybe CredentialPropertiesOutput
+ Crypto.WebAuthn.Encoding.Internal.WebAuthnJson: [$sel:rk:CredentialPropertiesOutput] :: CredentialPropertiesOutput -> Maybe Bool
+ Crypto.WebAuthn.Encoding.Internal.WebAuthnJson: newtype AuthenticationExtensionsClientInputs
+ Crypto.WebAuthn.Encoding.Internal.WebAuthnJson: newtype AuthenticationExtensionsClientOutputs
+ Crypto.WebAuthn.Encoding.Internal.WebAuthnJson: newtype CredentialPropertiesOutput
+ Crypto.WebAuthn.Encoding.Internal.WebAuthnJson: type JSON a :: Type;
+ Crypto.WebAuthn.Model.Types: type AttStmt a :: Type;
+ Crypto.WebAuthn.Model.Types: type AttStmtVerificationError a :: Type;
- Crypto.WebAuthn.Model.Identifier: [AuthenticatorIdentifierFido2] :: {idAaguid :: AAGUID} -> AuthenticatorIdentifier 'Fido2
+ Crypto.WebAuthn.Model.Identifier: [AuthenticatorIdentifierFido2] :: AAGUID -> AuthenticatorIdentifier 'Fido2
- Crypto.WebAuthn.Model.Identifier: [AuthenticatorIdentifierFidoU2F] :: {idSubjectKeyIdentifier :: SubjectKeyIdentifier} -> AuthenticatorIdentifier 'FidoU2F
+ Crypto.WebAuthn.Model.Identifier: [AuthenticatorIdentifierFidoU2F] :: SubjectKeyIdentifier -> AuthenticatorIdentifier 'FidoU2F
- Crypto.WebAuthn.Model.Types: [AttestationTypeVerifiable] :: {atvType :: VerifiableAttestationType " The type of verifiable attestation", atvChain :: AttestationChain p " The certificate chain of this attestation type, can be used to validate the authenticator model"} -> AttestationType ('Verifiable p)
+ Crypto.WebAuthn.Model.Types: [AttestationTypeVerifiable] :: VerifiableAttestationType -> AttestationChain p -> AttestationType ('Verifiable p)
- Crypto.WebAuthn.Model.Types: [AttestedCredentialData] :: {acdAaguid :: AAGUID " [(spec)](https://www.w3.org/TR/webauthn-2/#aaguid)", acdCredentialId :: CredentialId " [(spec)](https://www.w3.org/TR/webauthn-2/#credentialid)", acdCredentialPublicKey :: CosePublicKey " [(spec)](https://www.w3.org/TR/webauthn-2/#credentialpublickey)", acdCredentialPublicKeyBytes :: RawField raw " [(spec)](https://www.w3.org/TR/webauthn-2/#credentialpublickey)"} -> AttestedCredentialData 'Registration raw
+ Crypto.WebAuthn.Model.Types: [AttestedCredentialData] :: AAGUID -> CredentialId -> CosePublicKey -> RawField raw -> AttestedCredentialData 'Registration raw
- Crypto.WebAuthn.Model.Types: [AuthenticatorResponseAuthentication] :: {araClientData :: CollectedClientData 'Authentication raw " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-authenticatorresponse-clientdatajson) This attribute, inherited from `[AuthenticatorResponse](https://www.w3.org/TR/webauthn-2/#authenticatorresponse)`, contains the [JSON-compatible serialization of client data](https://www.w3.org/TR/webauthn-2/#collectedclientdata-json-compatible-serialization-of-client-data) (see [§ 6.5 Attestation](https://www.w3.org/TR/webauthn-2/#sctn-attestation)) passed to the authenticator by the client in order to generate this credential. The exact JSON serialization MUST be preserved, as the [hash of the serialized client data](https://www.w3.org/TR/webauthn-2/#collectedclientdata-hash-of-the-serialized-client-data) has been computed over it.", araAuthenticatorData :: AuthenticatorData 'Authentication raw " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-authenticatorassertionresponse-authenticatordata) This attribute contains the [authenticator data](https://www.w3.org/TR/webauthn-2/#authenticator-data) returned by the authenticator. See [§ 6.1 Authenticator Data](https://www.w3.org/TR/webauthn-2/#sctn-authenticator-data).", araSignature :: AssertionSignature " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-authenticatorassertionresponse-signature) This attribute contains the raw [assertion signature](https://www.w3.org/TR/webauthn-2/#assertion-signature) returned from the authenticator. See [§ 6.3.3 The authenticatorGetAssertion Operation](https://www.w3.org/TR/webauthn-2/#sctn-op-get-assertion).", araUserHandle :: Maybe UserHandle " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-authenticatorassertionresponse-userhandle) This attribute contains the [user handle](https://www.w3.org/TR/webauthn-2/#user-handle) returned from the authenticator, or null if the authenticator did not return a [user handle](https://www.w3.org/TR/webauthn-2/#user-handle). See [§ 6.3.3 The authenticatorGetAssertion Operation](https://www.w3.org/TR/webauthn-2/#sctn-op-get-assertion)."} -> AuthenticatorResponse 'Authentication raw
+ Crypto.WebAuthn.Model.Types: [AuthenticatorResponseAuthentication] :: CollectedClientData 'Authentication raw -> AuthenticatorData 'Authentication raw -> AssertionSignature -> Maybe UserHandle -> AuthenticatorResponse 'Authentication raw
- Crypto.WebAuthn.Model.Types: [AuthenticatorResponseRegistration] :: {arrClientData :: CollectedClientData 'Registration raw " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-authenticatorresponse-clientdatajson) This attribute, inherited from `[AuthenticatorResponse](https://www.w3.org/TR/webauthn-2/#authenticatorresponse)`, contains the [JSON-compatible serialization of client data](https://www.w3.org/TR/webauthn-2/#collectedclientdata-json-compatible-serialization-of-client-data) (see [§ 6.5 Attestation](https://www.w3.org/TR/webauthn-2/#sctn-attestation)) passed to the authenticator by the client in order to generate this credential. The exact JSON serialization MUST be preserved, as the [hash of the serialized client data](https://www.w3.org/TR/webauthn-2/#collectedclientdata-hash-of-the-serialized-client-data) has been computed over it.", arrAttestationObject :: AttestationObject raw " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-authenticatorattestationresponse-attestationobject) This attribute contains an [attestation object](https://www.w3.org/TR/webauthn-2/#attestation-object), which is opaque to, and cryptographically protected against tampering by, the client. The [attestation object](https://www.w3.org/TR/webauthn-2/#attestation-object) contains both [authenticator data](https://www.w3.org/TR/webauthn-2/#authenticator-data) and an [attestation statement](https://www.w3.org/TR/webauthn-2/#attestation-statement). The former contains the AAGUID, a unique [credential ID](https://www.w3.org/TR/webauthn-2/#credential-id), and the [credential public key](https://www.w3.org/TR/webauthn-2/#credential-public-key). The contents of the [attestation statement](https://www.w3.org/TR/webauthn-2/#attestation-statement) are determined by the [attestation statement format](https://www.w3.org/TR/webauthn-2/#attestation-statement-format) used by the [authenticator](https://www.w3.org/TR/webauthn-2/#authenticator). It also contains any additional information that the [Relying Party](https://www.w3.org/TR/webauthn-2/#relying-party)'s server requires to validate the [attestation statement](https://www.w3.org/TR/webauthn-2/#attestation-statement), as well as to decode and validate the [authenticator data](https://www.w3.org/TR/webauthn-2/#authenticator-data) along with the [JSON-compatible serialization of client data](https://www.w3.org/TR/webauthn-2/#collectedclientdata-json-compatible-serialization-of-client-data). For more details, see [§ 6.5 Attestation](https://www.w3.org/TR/webauthn-2/#sctn-attestation), [§ 6.5.4 Generating an Attestation Object](https://www.w3.org/TR/webauthn-2/#sctn-generating-an-attestation-object), and [Figure 6](https://www.w3.org/TR/webauthn-2/#fig-attStructs).", arrTransports :: [AuthenticatorTransport] " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-authenticatorattestationresponse-gettransports) This [internal slot](https://tc39.github.io/ecma262/#sec-object-internal-methods-and-internal-slots) contains a sequence of zero or more unique `[DOMString](https://heycam.github.io/webidl/#idl-DOMString)`s in lexicoaraphical order. These values are the transports that the [authenticator](https://www.w3.org/TR/webauthn-2/#authenticator) is believed to support, or an empty sequence if the information is unavailable."} -> AuthenticatorResponse 'Registration raw
+ Crypto.WebAuthn.Model.Types: [AuthenticatorResponseRegistration] :: CollectedClientData 'Registration raw -> AttestationObject raw -> [AuthenticatorTransport] -> AuthenticatorResponse 'Registration raw
- Crypto.WebAuthn.Model.Types: [CredentialOptionsAuthentication] :: {coaChallenge :: Challenge " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialrequestoptions-challenge) This member represents a challenge that the selected [authenticator](https://www.w3.org/TR/webauthn-2/#authenticator) signs, along with other data, when producing an [authentication assertion](https://www.w3.org/TR/webauthn-2/#authentication-assertion). See the [§ 13.4.3 Cryptographic Challenges](https://www.w3.org/TR/webauthn-2/#sctn-cryptographic-challenges) security consideration.", coaTimeout :: Maybe Timeout " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialrequestoptions-timeout) This OPTIONAL member specifies a time, in milliseconds, that the caller is willing to wait for the call to complete. The value is treated as a hint, and MAY be overridden by the [client](https://www.w3.org/TR/webauthn-2/#client).", coaRpId :: Maybe RpId " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialrequestoptions-rpid) This OPTIONAL member specifies the [relying party identifier](https://www.w3.org/TR/webauthn-2/#relying-party-identifier) claimed by the caller. If omitted, its value will be the `[CredentialsContainer](https://w3c.github.io/webappsec-credential-management/#credentialscontainer)` object’s [relevant settings object](https://html.spec.whatwg.org/multipage/webappapis.html#relevant-settings-object)'s [origin](https://html.spec.whatwg.org/multipage/webappapis.html#concept-settings-object-origin)'s [effective domain](https://html.spec.whatwg.org/multipage/origin.html#concept-origin-effective-domain).", coaAllowCredentials :: [CredentialDescriptor] " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialrequestoptions-allowcredentials) This OPTIONAL member contains a list of 'CredentialDescriptor' objects representing [public key credentials](https://www.w3.org/TR/webauthn-2/#public-key-credential) acceptable to the caller, in descending order of the caller’s preference (the first item in the list is the most preferred credential, and so on down the list). The default value of this field is 'Crypto.WebAuthn.Model.Defaults.coaAllowCredentialsDefault'.", coaUserVerification :: UserVerificationRequirement " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialrequestoptions-userverification) This OPTIONAL member describes the [Relying Party](https://www.w3.org/TR/webauthn-2/#relying-party)'s requirements regarding [user verification](https://www.w3.org/TR/webauthn-2/#user-verification) for the `[get()](https://w3c.github.io/webappsec-credential-management/#dom-credentialscontainer-get)` operation. The default value of this field is 'Crypto.WebAuthn.Model.Defaults.coaUserVerificationDefault'.", coaExtensions :: Maybe AuthenticationExtensionsClientInputs " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialrequestoptions-extensions) This OPTIONAL member contains additional parameters requesting additional processing by the client and authenticator. For example, if transaction confirmation is sought from the user, then the prompt string might be included as an extension. TODO: Extensions are not implemented by this library, see "Crypto.WebAuthn.Model.Types#extensions"."} -> CredentialOptions 'Authentication
+ Crypto.WebAuthn.Model.Types: [CredentialOptionsAuthentication] :: Challenge -> Maybe Timeout -> Maybe RpId -> [CredentialDescriptor] -> UserVerificationRequirement -> Maybe AuthenticationExtensionsClientInputs -> CredentialOptions 'Authentication
- Crypto.WebAuthn.Model.Types: [CredentialOptionsRegistration] :: {corRp :: CredentialRpEntity " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialcreationoptions-rp) This member contains data about the [Relying Party](https://www.w3.org/TR/webauthn-2/#relying-party) responsible for the request.", corUser :: CredentialUserEntity " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialcreationoptions-user) This member contains data about the user account for which the [Relying Party](https://www.w3.org/TR/webauthn-2/#relying-party) is requesting attestation.", corChallenge :: Challenge " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialcreationoptions-challenge) This member contains a challenge intended to be used for generating the newly created credential’s attestation object. See the [§ 13.4.3 Cryptographic Challenges](https://www.w3.org/TR/webauthn-2/#sctn-cryptographic-challenges) security consideration.", corPubKeyCredParams :: [CredentialParameters] " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialcreationoptions-pubkeycredparams) This member contains information about the desired properties of the credential to be created. The sequence is ordered from most preferred to least preferred. The [client](https://www.w3.org/TR/webauthn-2/#client) makes a best-effort to create the most preferred credential that it can.", corTimeout :: Maybe Timeout " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialcreationoptions-timeout) This member specifies a time, in milliseconds, that the caller is willing to wait for the call to complete. This is treated as a hint, and MAY be overridden by the [client](https://www.w3.org/TR/webauthn-2/#client).", corExcludeCredentials :: [CredentialDescriptor] " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialcreationoptions-excludecredentials) This member is intended for use by [Relying Parties](https://www.w3.org/TR/webauthn-2/#relying-party) that wish to limit the creation of multiple credentials for the same account on a single authenticator. The [client](https://www.w3.org/TR/webauthn-2/#client) is requested to return an error if the new credential would be created on an authenticator that also contains one of the credentials enumerated in this parameter. The default value of this field is 'Crypto.WebAuthn.Model.Defaults.corExcludeCredentials'.", corAuthenticatorSelection :: Maybe AuthenticatorSelectionCriteria " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialcreationoptions-authenticatorselection) This member is intended for use by [Relying Parties](https://www.w3.org/TR/webauthn-2/#relying-party) that wish to select the appropriate authenticators to participate in the [create()](https://w3c.github.io/webappsec-credential-management/#dom-credentialscontainer-create) operation.", corAttestation :: AttestationConveyancePreference " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialcreationoptions-attestation) This member is intended for use by [Relying Parties](https://www.w3.org/TR/webauthn-2/#relying-party) that wish to express their preference for [attestation conveyance](https://www.w3.org/TR/webauthn-2/#attestation-conveyance). The default value of this field is 'Crypto.WebAuthn.Model.Defaults.corAttestationDefault'.", corExtensions :: Maybe AuthenticationExtensionsClientInputs " [(spec)](https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialcreationoptions-extensions) This member contains additional parameters requesting additional processing by the client and authenticator. For example, the caller may request that only authenticators with certain capabilities be used to create the credential, or that particular information be returned in the [attestation object](https://www.w3.org/TR/webauthn-2/#attestation-object). Some extensions are defined in [§ 9 WebAuthn Extensions](https://www.w3.org/TR/webauthn-2/#sctn-extensions); consult the IANA "WebAuthn Extension Identifiers" registry [IANA-WebAuthn-Registries](https://www.w3.org/TR/webauthn-2/#biblio-iana-webauthn-registries) established by [RFC8809](https://www.w3.org/TR/webauthn-2/#biblio-rfc8809) for an up-to-date list of registered [WebAuthn Extensions](https://www.w3.org/TR/webauthn-2/#webauthn-extensions). TODO: Extensions are not implemented by this library, see "Crypto.WebAuthn.Model.Types#extensions"."} -> CredentialOptions 'Registration
+ Crypto.WebAuthn.Model.Types: [CredentialOptionsRegistration] :: CredentialRpEntity -> CredentialUserEntity -> Challenge -> [CredentialParameters] -> Maybe Timeout -> [CredentialDescriptor] -> Maybe AuthenticatorSelectionCriteria -> AttestationConveyancePreference -> Maybe AuthenticationExtensionsClientInputs -> CredentialOptions 'Registration
- Crypto.WebAuthn.Model.Types: [WithRaw] :: {unRaw :: ByteString} -> RawField 'True
+ Crypto.WebAuthn.Model.Types: [WithRaw] :: ByteString -> RawField 'True
- Crypto.WebAuthn.Operation.Registration: [UnverifiedAuthenticator] :: {uaFailures :: NonEmpty FailedReason " The failures that occurred when trying to validate the certificate chain", uaIdentifier :: AuthenticatorIdentifier p " The identifier for the authenticator model", uaMetadata :: Maybe (MetadataEntry p) " The metadata looked up in the provided 'Meta.MetadataServiceRegistry' This field is always equal to 'Meta.queryMetadata registry vaIdentifier', and is only provided for convenience and because the implementation already has to look it up"} -> AuthenticatorModel ('Verifiable p)
+ Crypto.WebAuthn.Operation.Registration: [UnverifiedAuthenticator] :: NonEmpty FailedReason -> AuthenticatorIdentifier p -> Maybe (MetadataEntry p) -> AuthenticatorModel ('Verifiable p)
- Crypto.WebAuthn.Operation.Registration: [VerifiedAuthenticator] :: {vaIdentifier :: AuthenticatorIdentifier p " The identifier for the authenticator model", vaMetadata :: Maybe (MetadataEntry p) " The metadata looked up in the provided 'Meta.MetadataServiceRegistry' This field is always equal to 'Meta.queryMetadata registry vaIdentifier', and is only provided for convenience and because the implementation already has to look it up"} -> AuthenticatorModel ('Verifiable p)
+ Crypto.WebAuthn.Operation.Registration: [VerifiedAuthenticator] :: AuthenticatorIdentifier p -> Maybe (MetadataEntry p) -> AuthenticatorModel ('Verifiable p)
Files
- changelog.md +4/−0
- src/Crypto/WebAuthn/AttestationStatementFormat/AndroidKey.hs +2/−1
- src/Crypto/WebAuthn/AttestationStatementFormat/AndroidSafetyNet.hs +5/−3
- src/Crypto/WebAuthn/AttestationStatementFormat/Apple.hs +1/−2
- src/Crypto/WebAuthn/AttestationStatementFormat/FidoU2F.hs +2/−1
- src/Crypto/WebAuthn/Cose/Internal/Verify.hs +1/−1
- src/Crypto/WebAuthn/Cose/PublicKey.hs +14/−14
- src/Crypto/WebAuthn/Cose/PublicKeyWithSignAlg.hs +14/−12
- src/Crypto/WebAuthn/Encoding/Binary.hs +15/−15
- src/Crypto/WebAuthn/Encoding/Internal/WebAuthnJson.hs +3/−0
- src/Crypto/WebAuthn/Operation/Authentication.hs +10/−7
- src/Crypto/WebAuthn/Operation/Registration.hs +8/−4
- tests/Main.hs +6/−5
- tests/Spec/Types.hs +8/−8
- webauthn.cabal +8/−8
changelog.md view
@@ -1,3 +1,7 @@+### 0.5.0.1++* [#159](https://github.com/tweag/webauthn/pull/159) Allow mtl-2.3.1 and support GHC 9.4+ ### 0.5.0.0 * [#157](https://github.com/tweag/webauthn/pull/157) Add support for the [credProps](https://www.w3.org/TR/webauthn-2/#sctn-authenticator-credential-properties-extension) extension
src/Crypto/WebAuthn/AttestationStatementFormat/AndroidKey.hs view
@@ -264,7 +264,8 @@ (CBOR.TString "alg", CBOR.TInt $ Cose.fromCoseSignAlg $ Cose.signAlg pubKeyAndAlg), ( CBOR.TString "x5c", CBOR.TList $- map (CBOR.TBytes . X509.encodeSignedObject) $ toList x5c+ map (CBOR.TBytes . X509.encodeSignedObject) $+ toList x5c ) ]
src/Crypto/WebAuthn/AttestationStatementFormat/AndroidSafetyNet.hs view
@@ -94,7 +94,7 @@ } deriving (Eq, Show, Generic, Aeson.FromJSON, Aeson.ToJSON) --- | Milliseconds represented as an 'Integer', used for 'timestampMs'+-- | Milliseconds represented as an 'Integer', used for @timestampMs@ newtype Milliseconds = Milliseconds Integer deriving (Eq, Show) deriving newtype (Aeson.FromJSON, Aeson.ToJSON)@@ -180,7 +180,8 @@ (Just (TString ver), Just (TBytes responseRaw)) -> do jws <- first (("Failed to decode compact JWT response blob: " <>) . Text.pack . show) $- runExcept @JOSE.Error $ JOSE.decodeCompact (LBS.fromStrict responseRaw)+ runExcept @JOSE.Error $+ JOSE.decodeCompact (LBS.fromStrict responseRaw) response <- first (("Failed to verify/decode JWT payload: " <>) . Text.pack . show) $ JOSE.verifyJWSWithPayload@@ -256,7 +257,8 @@ (True, False) -> BasicIntegrity (False, False) -> NoIntegrity unless (integrity >= requiredIntegrity) $- failure $ IntegrityCheckFailed integrity+ failure $+ IntegrityCheckFailed integrity -- 5. If successful, return implementation-specific values representing attestation type Basic and attestation trust -- path x5c.
src/Crypto/WebAuthn/AttestationStatementFormat/Apple.hs view
@@ -18,8 +18,7 @@ import qualified Codec.CBOR.Term as CBOR import Control.Exception (Exception)-import Control.Monad (forM)-import Control.Monad.Cont (unless)+import Control.Monad (forM, unless) import Crypto.Hash (Digest, SHA256, digestFromByteString, hash) import qualified Crypto.WebAuthn.Cose.Internal.Verify as Cose import qualified Crypto.WebAuthn.Cose.PublicKey as Cose
src/Crypto/WebAuthn/AttestationStatementFormat/FidoU2F.hs view
@@ -136,7 +136,8 @@ Just (xb, yb) -> do -- We decode the x and y values in an earlier stage of the process. In order to construct the publicKeyU2F, we have to reencode the value. unless (BS.length xb == 32 && BS.length yb == 32) $- failure $ CoordinateSizeInvalid (BS.length xb) (BS.length yb)+ failure $+ CoordinateSizeInvalid (BS.length xb) (BS.length yb) -- 4.c Let publicKeyU2F be the concatenation 0x04 || x || y. let publicKeyU2F = BS.singleton 0x04 <> xb <> yb
src/Crypto/WebAuthn/Cose/Internal/Verify.hs view
@@ -116,7 +116,7 @@ public_q = ECC.Point ecdsaX ecdsaY -- This check is already done in checkPublicKey- --unless (ECC.isPointValid public_curve public_q) $+ -- unless (ECC.isPointValid public_curve public_q) $ -- Left $ "ECDSA point is not valid for curve " <> Text.pack (show curveName) <> ": " <> Text.pack (show public_q) let key = ECDSA.PublicKey {..}
src/Crypto/WebAuthn/Cose/PublicKey.hs view
@@ -131,26 +131,26 @@ checkPublicKey key@PublicKeyEdDSA {..} | actualSize == expectedSize = Right $ CheckedPublicKey key | otherwise =- Left $- "EdDSA public key for curve "- <> Text.pack (show eddsaCurve)- <> " didn't have the expected size of "- <> Text.pack (show expectedSize)- <> " bytes, it has "- <> Text.pack (show actualSize)- <> " bytes instead: "- <> Text.decodeUtf8 (Base16.encode eddsaX)+ Left $+ "EdDSA public key for curve "+ <> Text.pack (show eddsaCurve)+ <> " didn't have the expected size of "+ <> Text.pack (show expectedSize)+ <> " bytes, it has "+ <> Text.pack (show actualSize)+ <> " bytes instead: "+ <> Text.decodeUtf8 (Base16.encode eddsaX) where actualSize = BS.length eddsaX expectedSize = coordinateSizeEdDSA eddsaCurve checkPublicKey key@PublicKeyECDSA {..} | ECC.isPointValid curve point = Right $ CheckedPublicKey key | otherwise =- Left $- "ECDSA public key point is not valid for curve "- <> Text.pack (show ecdsaCurve)- <> ": "- <> Text.pack (show point)+ Left $+ "ECDSA public key point is not valid for curve "+ <> Text.pack (show ecdsaCurve)+ <> ": "+ <> Text.pack (show point) where curve = ECC.getCurveByName (toCryptCurveECDSA ecdsaCurve) point = ECC.Point ecdsaX ecdsaY
src/Crypto/WebAuthn/Cose/PublicKeyWithSignAlg.hs view
@@ -237,23 +237,24 @@ os2ipWithSize size bytes | BS.length bytes == size = pure $ os2ip bytes | otherwise =- fail $- "bytes have length " <> show (BS.length bytes)- <> " when length "- <> show size- <> " was expected"+ fail $+ "bytes have length "+ <> show (BS.length bytes)+ <> " when length "+ <> show size+ <> " was expected" -- | Same as 'os2ip', but throws an error if there are leading zero bytes. Thus any successful result of this function will give the same 'BS.ByteString' back if encoded with 'i2osp'. os2ipNoLeading :: MonadFail m => BS.ByteString -> m Integer os2ipNoLeading bytes | leadingZeroCount == 0 = pure $ os2ip bytes | otherwise =- fail $- "bytes of length "- <> show (BS.length bytes)- <> " has "- <> show leadingZeroCount- <> " leading zero bytes when none were expected"+ fail $+ "bytes of length "+ <> show (BS.length bytes)+ <> " has "+ <> show leadingZeroCount+ <> " leading zero bytes when none were expected" where leadingZeroCount = BS.length (BS.takeWhile (== 0) bytes) @@ -262,7 +263,8 @@ decodeExpected expected = do actual <- decode unless (expected == actual) $- fail $ "Expected " <> show expected <> " but got " <> show actual+ fail $+ "Expected " <> show expected <> " but got " <> show actual fromCurveEdDSA :: P.CoseCurveEdDSA -> R.CoseEllipticCurveOKP fromCurveEdDSA P.CoseCurveEd25519 = R.CoseEllipticCurveEd25519
src/Crypto/WebAuthn/Encoding/Binary.hs view
@@ -77,9 +77,9 @@ The functions in this module are grouped and named according to the following conventions: -* If the type is parametrized by @raw@, there should be @stripRaw@ and+ * If the type is parametrized by @raw@, there should be @stripRaw@ and @encodeRaw@ functions-* If the type is serializable there should be a @decode@+ * If the type is serializable there should be a @decode@ * In addition, if the type has a raw field for its own encoding (implying that it's parametrized by @raw@), no other function needs to be provided * Alternatively, there should be an @encode@ that encodes the type, using@@ -88,9 +88,9 @@ If the type is parametrized by @raw@, this module should guarantee these invariants for any @value :: TheType (raw ~ False)@: -* @stripRaw@ doesn't change any fields: @stripRaw value = value@-* @encodeRaw@ doesn't change any fields: @stripRaw (encodeRaw value) = value@-* If the type is also serializable:+ * @stripRaw@ doesn't change any fields: @stripRaw value = value@+ * @encodeRaw@ doesn't change any fields: @stripRaw (encodeRaw value) = value@+ * If the type is also serializable: * If the type has a raw field, @decode@ inverses @encodeRaw@ and @getEncoded@: @stripRaw (decode (getEncoded (encodeRaw value))) = value@ * Alternatively, @decode@ inverses @encodeRaw@ and @encode@:@@ -99,7 +99,7 @@ If the type is only serializable then this invariant should hold for any @value :: TheType@ -* @decode@ inverses @encode@: @decode (encode value) = value@+ * @decode@ inverses @encode@: @decode (encode value) = value@ If any such functions are expected to be used only internally, they may not be exported@@ -111,13 +111,13 @@ -- custom binary format the -- [binary](https://hackage.haskell.org/package/binary) library. However these -- two libraries don't interact nicely with each other. Because of this we are--- specifying decoders that don't consume all input as a 'PartialBinaryDecoder--- DecodingError', which is just a function that can partially consume a--- 'LBS.ByteString'. Using this we can somewhat easily flip between the two+-- specifying decoders that don't consume all input as a @PartialBinaryDecoder@,+-- which is just a state monad transformer over an 'LBS.ByteString'.+-- Using this we can somewhat easily flip between the two -- libraries while decoding without too much nastiness. type PartialBinaryDecoder a = StateT LBS.ByteString (Either Text) a --- | Runs a 'PartialBinaryDecoder' using a strict bytestring. Afterwards it+-- | Runs a @PartialBinaryDecoder@ using a strict bytestring. Afterwards it -- makes sure that no bytes are left, otherwise returns an error. runPartialBinaryDecoder :: BS.ByteString ->@@ -129,11 +129,11 @@ Right (result, rest) | LBS.null rest -> return result | otherwise ->- Left $- "Not all binary input used, rest in base64 format is: "- <> decodeUtf8 (Base64.encode $ LBS.toStrict rest)+ Left $+ "Not all binary input used, rest in base64 format is: "+ <> decodeUtf8 (Base64.encode $ LBS.toStrict rest) --- | A 'PartialBinaryDecoder' for a binary encoding specified using+-- | A @PartialBinaryDecoder@ for a binary encoding specified using -- 'Binary.Get'. runBinary :: Binary.Get a ->@@ -147,7 +147,7 @@ put rest pure result --- | A 'PartialBinaryDecoder' for a CBOR encoding specified using the given+-- | A @PartialBinaryDecoder@ for a CBOR encoding specified using the given -- 'CBOR.Decoder'. runCBOR :: (forall s. CBOR.Decoder s a) ->
src/Crypto/WebAuthn/Encoding/Internal/WebAuthnJson.hs view
@@ -23,6 +23,9 @@ PublicKeyCredentialRpEntity (..), PublicKeyCredentialUserEntity (..), PublicKeyCredentialParameters (..),+ AuthenticationExtensionsClientInputs (..),+ AuthenticationExtensionsClientOutputs (..),+ CredentialPropertiesOutput (..), COSEAlgorithmIdentifier, PublicKeyCredentialDescriptor (..), AuthenticatorSelectionCriteria (..),
src/Crypto/WebAuthn/Operation/Authentication.hs view
@@ -245,17 +245,17 @@ case (midentifiedUser, mUserHandler) of (Just identifiedUser, Just userHandle) | identifiedUser /= owner ->- failure $ AuthenticationIdentifiedUserHandleMismatch identifiedUser owner+ failure $ AuthenticationIdentifiedUserHandleMismatch identifiedUser owner | userHandle /= owner ->- failure $ AuthenticationCredentialUserHandleMismatch userHandle owner+ failure $ AuthenticationCredentialUserHandleMismatch userHandle owner | otherwise -> pure () (Just identifiedUser, Nothing) | identifiedUser /= owner ->- failure $ AuthenticationIdentifiedUserHandleMismatch identifiedUser owner+ failure $ AuthenticationIdentifiedUserHandleMismatch identifiedUser owner | otherwise -> pure () (Nothing, Just userHandle) | userHandle /= owner ->- failure $ AuthenticationCredentialUserHandleMismatch userHandle owner+ failure $ AuthenticationCredentialUserHandleMismatch userHandle owner | otherwise -> pure () (Nothing, Nothing) -> failure AuthenticationCannotVerifyUserHandle@@ -286,11 +286,13 @@ -- 12. Verify that the value of C.challenge equals the base64url encoding of options.challenge. unless (M.ccdChallenge c == M.coaChallenge options) $- failure $ AuthenticationChallengeMismatch (M.coaChallenge options) (M.ccdChallenge c)+ failure $+ AuthenticationChallengeMismatch (M.coaChallenge options) (M.ccdChallenge c) -- 13. Verify that the value of C.origin matches the Relying Party's origin. unless (M.ccdOrigin c == origin) $- failure $ AuthenticationOriginMismatch origin (M.ccdOrigin c)+ failure $+ AuthenticationOriginMismatch origin (M.ccdOrigin c) -- 14. Verify that the value of C.tokenBinding.status matches the state of -- Token Binding for the TLS connection over which the attestation was@@ -305,7 +307,8 @@ -- Note: If using the appid extension, this step needs some special logic. -- See § 10.1 FIDO AppID Extension (appid) for details. unless (M.adRpIdHash authData == rpIdHash) $- failure $ AuthenticationRpIdHashMismatch rpIdHash (M.adRpIdHash authData)+ failure $+ AuthenticationRpIdHashMismatch rpIdHash (M.adRpIdHash authData) -- 16. Verify that the User Present bit of the flags in authData is set. unless (M.adfUserPresent (M.adFlags authData)) $
src/Crypto/WebAuthn/Operation/Registration.hs view
@@ -334,11 +334,13 @@ -- 8. Verify that the value of C.challenge equals the base64url encoding of -- options.challenge. unless (corChallenge == M.ccdChallenge c) $- failure $ RegistrationChallengeMismatch corChallenge (M.ccdChallenge c)+ failure $+ RegistrationChallengeMismatch corChallenge (M.ccdChallenge c) -- 9. Verify that the value of C.origin matches the Relying Party's origin. unless (rpOrigin == M.ccdOrigin c) $- failure $ RegistrationOriginMismatch rpOrigin (M.ccdOrigin c)+ failure $+ RegistrationOriginMismatch rpOrigin (M.ccdOrigin c) -- 10. Verify that the value of C.tokenBinding.status matches the state of -- Token Binding for the TLS connection over which the assertion was@@ -363,7 +365,8 @@ -- 13. Verify that the rpIdHash in authData is the SHA-256 hash of the RP -- ID expected by the Relying Party. unless (rpIdHash == M.adRpIdHash authData) $- failure $ RegistrationRpIdHashMismatch rpIdHash (M.adRpIdHash authData)+ failure $+ RegistrationRpIdHashMismatch rpIdHash (M.adRpIdHash authData) -- 14. Verify that the User Present bit of the flags in authData is set. unless (M.adfUserPresent (M.adFlags authData)) $@@ -391,7 +394,8 @@ let acdAlg = Cose.signAlg acdCredentialPublicKey desiredAlgs = map M.cpAlg corPubKeyCredParams unless (acdAlg `elem` desiredAlgs) $- failure $ RegistrationPublicKeyAlgorithmDisallowed desiredAlgs acdAlg+ failure $+ RegistrationPublicKeyAlgorithmDisallowed desiredAlgs acdAlg -- 17. Verify that the values of the client extension outputs in -- clientExtensionResults and the authenticator extension outputs in the
tests/Main.hs view
@@ -345,10 +345,10 @@ isExpectedAttestationResponse M.Credential {..} M.CredentialOptionsRegistration {..} verifiable (Right O.RegistrationResult {..}) = rrEntry == expectedCredentialEntry && not verifiable- || ( case rrAttestationStatement of- O.SomeAttestationStatement _ O.VerifiedAuthenticator {} -> True- _ -> False- )+ || ( case rrAttestationStatement of+ O.SomeAttestationStatement _ O.VerifiedAuthenticator {} -> True+ _ -> False+ ) where expectedCredentialEntry :: O.CredentialEntry expectedCredentialEntry =@@ -356,7 +356,8 @@ { ceCredentialId = cIdentifier, ceUserHandle = M.cueId corUser, cePublicKeyBytes =- M.PublicKeyBytes . M.unRaw+ M.PublicKeyBytes+ . M.unRaw . M.acdCredentialPublicKeyBytes . M.adAttestedCredentialData . M.aoAuthData
tests/Spec/Types.hs view
@@ -119,11 +119,11 @@ arbitrary = M.CollectedClientData <$> arbitrary- <*> arbitrary- -- The crossOrigin value can't be roundtripped with Nothing values,- -- so let's just not generate Nothing values here- <*> (Just <$> arbitrary)- <*> arbitrary+ <*> arbitrary+ -- The crossOrigin value can't be roundtripped with Nothing values,+ -- so let's just not generate Nothing values here+ <*> (Just <$> arbitrary)+ <*> arbitrary instance Arbitrary (M.AttestationObject 'False) where arbitrary = do@@ -142,9 +142,9 @@ arbitrary = elements [ ArbitraryAttestationStatementFormat None.Format- --ArbitraryAttestationStatementFormat Packed.Format,- --ArbitraryAttestationStatementFormat FidoU2F.Format,- --ArbitraryAttestationStatementFormat AndroidKey.Format+ -- ArbitraryAttestationStatementFormat Packed.Format,+ -- ArbitraryAttestationStatementFormat FidoU2F.Format,+ -- ArbitraryAttestationStatementFormat AndroidKey.Format ] instance Arbitrary M.SignatureCounter where
webauthn.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: webauthn-version: 0.5.0.0+version: 0.5.0.1 license: Apache-2.0 license-file: LICENSE copyright:@@ -35,7 +35,7 @@ however follow the [PVP](https://pvp.haskell.org/) and properly label changes with the appropriate version increase. category: Web, Authentication-tested-with: GHC == 8.10.7+tested-with: GHC == 9.2.4 extra-source-files: README.md, changelog.md,@@ -73,7 +73,7 @@ import: sanity hs-source-dirs: src build-depends:- base >= 4.13.0 && < 4.17,+ base >= 4.13.0 && < 4.18, aeson >= 1.4.7 && < 2.2, asn1-encoding >= 0.9.6 && < 0.10, asn1-parse >= 0.9.5 && < 0.10,@@ -88,14 +88,14 @@ file-embed >= 0.0.11 && < 0.1, hashable >= 1.3.0 && < 1.5, hourglass >= 0.2.12 && < 0.3,- jose >= 0.8.5 && < 0.10,- lens >= 4.18.1 && < 5.2,- memory >= 0.15.0 && < 0.18,+ jose >= 0.8.5 && < 0.11,+ lens >= 4.18.1 && < 5.3,+ memory >= 0.15.0 && < 0.19, monad-time >= 0.3.1 && < 0.5,- mtl >= 2.2.2 && < 2.3,+ mtl >= 2.2.2 && < 2.4, serialise >= 0.2.3 && < 0.3, singletons >= 2.6 && < 3.2,- text >= 1.2.4 && < 1.3,+ text >= 1.2.4 && < 2.1, time >= 1.9.3 && < 1.12, unordered-containers >= 0.2.11 && < 0.3, uuid >= 1.3.13 && < 1.4,