޲֤Q      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOP,Miscellany. Mostly to do with serialization.NoneTake an arbitrary sequence of bytes and expand it to be the given number of bytes. Do this by extracting a pseudo-random key and expanding it using HKDF.1Given a seed value for an arbitrary element (see arbitraryElement(), expand it to be of the given length.4Serialize a number according to the SPAKE2 protocol.ZJust kidding, there isn't a SPAKE2 protocol. This just matches the Python implementation. Inverse of .4Serialize a number according to the SPAKE2 protocol.FPanics if the number is too big to fit into the given number of bytes.6Deserialize a number according to the SPAKE2 protocol.ZJust kidding, there isn't a SPAKE2 protocol. This just matches the Python implementation. Inverse of ."Interfaces for mathematical groupsNoneDRgA group key pair composed of the private part (a scalar) and a public part (associated group element). A group where  is commutative.That is, where4\x y -> elementAdd group x y == elementAdd group y x!This property leads to a natural  \mathbb{Z}G-module, where scalar multiplication is defined as repeatedly calling . DefinitionsWarning: this gets algebraic.A module is a ring R together with an abelian group (G, +), and a new operator \cdot) (i.e. scalar multiplication) such that: 'r \cdot (x + y) = r \cdot x + r \cdot y'(r + s) \cdot x = r \cdot x + s \cdot x"(rs) \cdot x = r \cdot (s \cdot x)1_R \cdot x = xfor all x, y in G, and r, s in R , where 1_R is the identity of the ring.A ring  R, +, \cdot a set R with two operators such that: R is an abelian group under +R is a monoid under \cdotcdot# is _distributive_ with respect to + . That is,?(a cdot (b + c) = (a cdot b) + (a cdot c) (left distributivity)A((b + c) cdot a) = (b cdot a) + (c cdot a) (right distributivity)=Note we have to define left & right distributivity, because \cdot might not be commutative.A monoid9 is a group without the notion of inverse. See Haskell's Q typeclass.A  \mathbb{Z}#-module is a module where the ring R: is the integers with normal addition and multiplication. ~A scalar for this group. Mathematically equivalent to an integer, but possibly stored differently for computational reasons. :Multiply an element of the group with respect to a scalar.This is equivalent to adding the element to itself N times, where N is a scalar. The default implementation does exactly that. .Get the scalar that corresponds to an integer.Note [Added for completeness]:\x -> scalarToInteger group (integerToScalar group x) == x -Get the integer that corresponds to a scalar.Note [Added for completeness]:\x -> integerToScalar group (scalarToInteger group x) == xSize of scalars, in bitseEncode a scalar into bytes. | Generate a new random element of the group, with corresponding scalar.5A mathematical group intended to be used with SPAKE2.An element of the group.Group addition.`\x y z -> elementAdd group (elementAdd group x y) z == elementAdd group x (elementAdd group y z)'Inverse with respect to group addition.C\x -> (elementAdd group x (elementNegate group x)) == groupIdentity8\x -> (elementNegate group (elementNegate group x)) == x"Subtract one element from another.S\x y -> (elementSubtract group x y) == (elementAdd group x (elementNegate group y))Identity of the group.Note [Added for completeness]-\x -> (elementAdd group x groupIdentity) == x-\x -> (elementAdd group groupIdentity x) == x*Encode an element of the group into bytes.Note [Byte encoding in Group]C\x -> decodeElement group (encodeElement group x) == CryptoPassed x1Decode an element into the group from some bytes.Note [Byte encoding in Group]Size of elements, in bitsEDeterministically create an arbitrary element from a seed bytestring.XXX=: jml would much rather this take a scalar, an element, or even an integer, rather than bytes because bytes mean that the group instances have to know about hash algorithms and HKDF. If the IntegerGroup class in SPAKE2 also oversized its input, then it and the ed25519 implementation would have identical decoding.2Map some arbitrary bytes into a scalar in a group.%Size of elements in a group, in bits.%Size of scalars in a group, in bytes.      Ed25519 group for SPAKE2None !#,DR_RHA point that might be a member of Ed25519. Note: [Extended coordinates]S8Whether or not an extended point is a member of Ed25519.T'Errors that can occur within the group.U.Translate internal errors into CryptoFailable.V0Guarantee an element is in the Ed25519 subgroup.W/Assert that an element is the Ed25519 subgroup.Panics if it is not.X&The order of the group represented by .>Note that this is a subgroup of the underlying elliptic curve.Y0The generator for the (sub)group represented by .ZCalculate the inverse of x modulo [. Assumes that x is coprime with [P and non-zero. Will raise an exception if either of these assumptions is false.\x -> (x * inv x) `mod` q == 1\&Zero in the extended coordinate space. RaffineZero = AffinePoint{x = 0, y = 1} extendedZero == affineToExtended affineZeroNote: [Extended coordinates]]'Check if a point is equivalent to zero.{jml is unsure, but this probably exists because it might be faster than mapping to affine space and checking for equality.Note: [Extended coordinates]^Add two extended points.qThe points don't have to be in the Ed25519 subgroup, and we can't say anything about whether the result will be.add-2008-hwcd-3_Double an extended point. dbl-2008-hwcd`Negate an extended point.a@Multiply a point (might be in the group, might not) by a scalar.b/Scalar multiplication parametrised by addition.c5Attempt to create a member of Ed25519 from an affine y coordinate.d0Construct an affine point that is on Curve25519.e Encode an f into bytes.$MSB of the output is whether or not x is even (i.e. x .&. 1,), teh rest of the output is little-endian y./fghiRjklmnSopTqrsUVW[XtuYZv\]^_`abcdewxyz{|}~XY!fghiRjklmnSopTqrsUVW[XtuYZv\]^_`abcdewxyz{|}~(Multiplicative group of integers modulo nNone#DRQA finite group of integers with respect to multiplication modulo the group order.Construct with $.$ Construct an .Will fail if generator is '1'T, since having the identity for a generator means the subgroup is the entire group..TODO: Find other things to check for validity.%1024 bit integer group.Originally from  /http://haofeng66.googlepages.com/JPAKEDemo.java, via  'https://github.com/warner/python-spake2 python-spake2.  !"#$% #!"$% !"#$%-Implementation of various mathematical groupsNone  #!"$%  !"#$%*The mathematical implementation of SPAKE2.None#: &*A SPAKE2 exchange that has been initiated.Description of the specific instance of the SPAKE2 protocol we are using. Parameters, password, and group must be the same for this to work.Arbitrary element and scalar chosen by this side of the exchange. It is kept secret, and is only used to negotiate an exchange. A "blinded" form is sent to the other side of the protocol.'MAn instance of the SPAKE2 protocol. This represents one side of the protocol.+vThe parameters of the SPAKE2 protocol. The other side needs to be using the same values, but with swapped values for . and /.-)The cyclic group used for encrypting keys.EThe "blind" we use when sending out values. Side A refers to this as M in the protocol description./NThe "blind" the other side uses when sending values. Side A refers to this as N in the protocol description.02Initiate the SPAKE2 exchange. Generates a secret (xyW) that will be held by this side, and transmitted to the other side in "blinded" form.1Determine the element (either  X^{\star} or  Y^{\star}) to send to the other side.2Generate key material, K/, given a message from the other side (either  Y^{\star} or  X^{\star}).PThis key material is the last piece of input required to make the session key, SK, which should be generated as:2SK \leftarrow H(A, B, X^{\star}, Y^{\star}, K, pw)Where:H is a hash functionA identifies the initiating sideB identifies the receiving sideX^{star}1 is the outbound message from the initiating sideY^{star}0 is the outbound message from the receiving sideK is the result of this functionpw; is the password (this is what makes it SPAKE2, not SPAKE1)&'()*+,-./012An initiated SPAKE2 exchange=The outbound message from the other side (i.e. inbound to us)<The final piece of key material to generate the session key. &'()*+,-./012 '()*+,-./0&12&'()*+,-./012.Implementation of SPAKE2 key exchange protocolNone#3,Everything required for the SPAKE2 protocol.FBoth sides must agree on these values for the protocol to work. This mostly" means value equality, except for  2, where each side must have complementary values.Construct with @ or A.The group to use for encryption2Hash algorithm used for generating the session key&How the two sides relate to each otherhRelation between two sides in SPAKE2. Can be either symmetric (both sides are the same), or asymmetric./Side A. Both sides need to agree who side A is./Side B. Both sides need to agree who side B is.Which side we areDescription used by both sides.4Which side we are. One side of the SPAKE2 protocol.Bytes identifying this sideVArbitrarily chosen element in the group used by this side to blind outgoing messages.7TAn error that occurs when interpreting messages from the other side of the exchange. We received an empty bytestring.EThe bytestring had an unexpected prefix. We expect the prefix to be A if the other side is side A, B if they are side B, or SX if the connection is symmetric. First argument is received prefix, second is expected.Message could not be decoded to an element of the group. This can indicate either an error in serialization logic, or in mathematics..An error arising from the "receive" action in B. Since 0.4.08*Bytes that identify a side of the protocol;8Shared secret password used to negotiate the connection.7Constructor deliberately not exported, so that once a ;L has been created, the actual password cannot be retrieved by other modules.Construct with <.<Construct a password.:Convert a user-supplied password into a scalar on a group.=>Turn an element into a message from this side of the protocol.>Turn a 7 into human-readable text.?9Extract an element on the group from an incoming message. Returns a 7c if we cannot decode the message, or the other side does not appear to be the expected other side.>TODO: Need to protect against reflection attack at some point.@(Construct an asymmetric SPAKE2 protocol.A&Construct a symmetric SPAKE2 protocol.WGet the parameters for the mathematical part of SPAKE2 from the protocol specification.B"Perform an entire SPAKE2 exchange.Given a SPAKE2 protocol that has all of the parameters for this exchange, generate a one-off message from this side and receive a one off message from the other.OOnce we are done, return a key shared between both sides for a single session.SNote: as per the SPAKE2 definition, the session key is not guaranteed to actually work. If the other side has failed to authenticate, you will still get a session key. Therefore, you must exchange some other message that has been encrypted using this key in order to confirm that the session key is indeed shared.5Note: the "send" and "receive" actions are performed 7. If you have ordering requirements, consider using a TVar or 8 to coordinate, or implementing your own equivalent of B.HIf the message received from the other side cannot be parsed, return a 7. Since 0.4.0.CCommence a SPAKE2 exchange.D3Create a session key based on the output of SPAKE2.2SK \leftarrow H(A, B, X^{\star}, Y^{\star}, K, pw) Including pw: in the session key is what makes this SPAKE2, not SPAKE1.Note!: In spake2 0.3 and earlier, The  X^{\star} and  Y^{\star}D were expected to be from side A and side B respectively. Since spake2 0.4, they are the outbound and inbound elements respectively. This fixes an interoperability concern with the Python library, and reduces the burden on the caller. Apologies for the possibly breaking change to any users of older versions of spake2.)3456789:;<=>?@ABA 3j with all the parameters for the exchange. These parameters must be shared by both sides. Construct with @ or A.7The password shared between both sides. Construct with <.!An action to send a message. The z parameter is this side's SPAKE2 element, encoded using the group encoding, prefixed according to the parameters in the 3.$An action to receive a message. The i generated ought to be the protocol-prefixed, group-encoded version of the other side's SPAKE2 element.aEither the shared session key or an error indicating we couldn't parse the other side's message.CD#The protocol used for this exchange)The outbound message, generated by this,  X^{\star}, or either side if symmetric2The inbound message, generated by the other side,  Y^{\star}, or either side if symmetricThe calculated key material, KThe shared secret password.A session key to use for further communication123456789:;<=>?@ABCD;<3@ABC12?7>=D89:4563456789:;<=>?@ABCD     !"#$%&&''()*+,-../01123456789:;<==>?@ABCDEF5GHIJKLMNOPQRSTUVWXYZ[\]*^_`abcdefghijjklWmnopqrstuvwxyz{|}~2 T8?"spake2-0.4.1-37XSOJtz1ZJ7PXMnsdtorCrypto.Spake2.UtilCrypto.Spake2.GroupCrypto.Spake2.GroupsCrypto.Spake2.Math Crypto.Spake2Crypto.Spake2.Groups.Ed25519!Crypto.Spake2.Groups.IntegerGroupRelationus expandDataexpandArbitraryElementSeed numberToBytesunsafeNumberToBytes bytesToNumberKeyPair keyPairPublickeyPairPrivate AbelianGroupScalarscalarMultiplyintegerToScalarscalarToIntegerscalarSizeBitsgenerateElementGroupElement elementAdd elementNegateelementSubtract groupIdentity encodeElement decodeElementelementSizeBitsarbitraryElement decodeScalarelementSizeBytesscalarSizeBytesEd25519 IntegerGrouporder subgroupOrder generatormakeIntegerGroupi1024Spake2ExchangeSpake2paramspasswordParamsgroupourBlind theirBlind startSpake2computeOutboundMessagegenerateKeyMaterialProtocol WhichSideSideASideB MessageErrorSideIDunSideIDPassword makePasswordelementToMessage formatErrorextractElementmakeAsymmetricProtocolmakeSymmetricProtocolspake2ExchangecreateSessionKey $fEqPassword $fOrdPassword $fEqSideID $fOrdSideID $fShowSideID$fEqMessageError$fShowMessageError $fEqWhichSide$fOrdWhichSide$fShowWhichSide$fBoundedWhichSide$fEnumWhichSidebaseGHC.BaseMonoid ExtendedPointGroupMembershipErrortoCryptoFailable ensureInGroup assertInGrouplinvq extendedZeroisExtendedZeroaddExtendedPointsdoubleExtendedPointnegateExtendedPointsafeScalarMultiplyscalarMultiplyExtendedPointmakeGroupMembermakeAffinePointencodeAffinePoint AffinePoint$sel:x:AffinePoint$sel:y:AffinePoint$sel:x:ExtendedPoint$sel:y:ExtendedPoint$sel:z:ExtendedPoint$sel:t:ExtendedPointUnknownMember NotOnCurve NotInGroup LowOrderPointdConstixRecoverdecodeAffinePointnumberToLitteEndianByteslittleEndianBytesToNumberaffineToExtendedextendedToAffine'$fEqExtendedPoint$fAbelianGroupEd25519$fGroupEd25519$fAbelianGroupIntegerGroup$fGroupIntegerGroupspake2xyStarted hashAlgorithmrelationsideAsideB bothSidesSidesideIDblind EmptyMessageUnexpectedPrefix BadCrypto UnknownErrorpasswordToScalar getParams$async-2.1.1.1-8yywY4inVGRLJSCg60gBXjControl.Concurrent.Async concurrentlyGHC.MVarMVar Asymmetric Symmetric theirPrefixbytestring-0.10.8.1Data.ByteString.Internal ByteString