úο!·aP      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO,Miscellany. Mostly to do with serialization.None›Take 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 P 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_QHA point that might be a member of Ed25519. Note: [Extended coordinates]R8Whether or not an extended point is a member of Ed25519.S'Errors that can occur within the group.T.Translate internal errors into CryptoFailable.U0Guarantee an element is in the Ed25519 subgroup.V/Assert that an element is the Ed25519 subgroup.Panics if it is not.W&The order of the group represented by .>Note that this is a subgroup of the underlying elliptic curve.X0The generator for the (sub)group represented by .YCalculate the inverse of x modulo Z. Assumes that x is coprime with ZP 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_@Multiply a point (might be in the group, might not) by a scalar.`/Scalar multiplication parametrised by addition.a5Attempt to create a member of Ed25519 from an affine y coordinate.b0Construct an affine point that is on Curve25519.c Encode an d 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..defgQhijklRmnSopqTUVZWrsXYt[\]^_`abcuvwxyz{|WX defgQhijklRmnSopqTUVZWrsXYt[\]^_`abcuvwxyz{|(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 encryptionƒ2Hash algorithm used for generating the session key„&How the two sides relate to each other…hRelation 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 are‰Description used by both sides.4Which side we are.Š One side of the SPAKE2 protocol.‹Bytes identifying this sideŒVArbitrarily 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.8*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.BCommence a SPAKE2 exchange.C3Create 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.'3’‚ƒ„…“”†‡ˆ‰456Š•‹Œ7Ž89:;–<=>?—@A‘BC#The protocol used for this exchangeThe message from side A,  X^{\star}, or either side if symmetricThe message from side B,  Y^{\star}, or either side if symmetricThe calculated key material, KThe shared secret password.A session key to use for further communication123456789:;<=>?@ABC;<3@AB12?7>=C89:4563’‚ƒ„…“”†‡ˆ‰456Š•‹Œ7Ž89:;–<=>?—@A‘BC˜     !"#$%&&''()*+,-../01123456789:;<==>?@ABCDE5FGHIJKLMNOPQRSTUVWXYZ[\*]^_`abcdefghhijVklmnopqrstuvwxyz{|}~€‚ƒ2„…†‡ ˆ‰Š‹ŒŽ8‘’‰?“”#spake2-0.2.0-1CgD4hiLZdg4ZerhggRckdCrypto.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 formatErrorextractElementmakeAsymmetricProtocolmakeSymmetricProtocolcreateSessionKey $fEqPassword $fOrdPassword $fEqSideID $fOrdSideID $fShowSideID$fEqMessageError$fShowMessageError $fEqWhichSide$fOrdWhichSide$fShowWhichSide$fBoundedWhichSide$fEnumWhichSidebaseGHC.BaseMonoid ExtendedPointGroupMembershipErrortoCryptoFailable ensureInGroup assertInGrouplinvq extendedZeroisExtendedZeroaddExtendedPointsdoubleExtendedPointsafeScalarMultiplyscalarMultiplyExtendedPointmakeGroupMembermakeAffinePointencodeAffinePoint 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 BadCryptopasswordToScalar getParams Asymmetric Symmetric theirPrefix