Example #1
0
        /// <summary>
        ///     Creates a round 2 (zero-knowledge proof) DTO to send to the partner participant.
        /// </summary>
        /// <exception cref="InvalidOperationException">
        ///     Prior round (1) has not been completed yet, or method may have been called more than once.
        /// </exception>
        public ECJpakeRound2 CreateRound2ToSend()
        {
            if (ProtocolState >= State.Round2Created)
            {
                throw new InvalidOperationException("Round 2 payload already created.");
            }
            if (ProtocolState < State.Round1Validated)
            {
                throw new InvalidOperationException("Round 1 payload must be validated prior to creating Round 2 payload.");
            }

            var s1 = new BigInteger(_passwordBytes);

            ECPoint    GA   = _gx1.Add(_gx3).Add(_gx4);
            BigInteger x2s1 = _x2.Multiply(s1).Mod(_domain.N);
            ECPoint    A    = BasePointMultiplier.Multiply(GA, x2s1);

            ECPoint    X2sV;
            BigInteger X2sR;

            CreateZeroKnowledgeProof(GA, x2s1, A, ParticipantId, out X2sV, out X2sR);

            var dto = new ECJpakeRound2 {
                ParticipantId = ParticipantId,
                A             = A.GetEncoded(),
                X2sV          = X2sV.GetEncoded(),
                X2sR          = X2sR.ToByteArray()
            };

            ProtocolState = State.Round2Created;
            return(dto);
        }
Example #2
0
        /// <summary>
        ///     Validates the round 2 (zero-knowledge proof) DTO received from the partner participant.
        /// </summary>
        /// <param name="round2Received">Round 2 DTO received form partner participant.</param>
        /// <exception cref="InvalidOperationException">
        ///     Prior round (1) has not been completed yet, or method may have been called more than once.
        /// </exception>
        /// <exception cref="CryptoException">
        ///     Verification of zero-knowledge proof failed. Possible attempted impersonation, e.g. MiTM.
        /// </exception>
        public void ValidateRound2Received(ECJpakeRound2 round2Received)
        {
            Contract.Requires <InvalidOperationException>(ProtocolState < State.Round2Validated,
                                                          "Validation already attempted for round 2 payload.");
            Contract.Requires <InvalidOperationException>(ProtocolState > State.Round1Validated,
                                                          "Round 1 payload must be validated prior to validating round 2 payload.");

            Contract.Requires <ConfigurationInvalidException>(String.IsNullOrEmpty(round2Received.ParticipantId) == false,
                                                              "Partner participant ID in round 2 DTO received is null or empty.");
            Contract.Requires <CryptoException>(PartnerParticipantId.Equals(round2Received.ParticipantId, StringComparison.Ordinal),
                                                "Partner participant ID of round 2 DTO does not match value from round 1.");

            ECPoint X4sV = _domain.Curve.DecodePoint(round2Received.X2sV);
            var     X4sR = new BigInteger(round2Received.X2sR);

            _b = _domain.Curve.DecodePoint(round2Received.A);
            // Calculate GB : GX1 + GX3 + GX4 symmetrically
            ECPoint GB = _gx3.Add(_gx1).Add(_gx2);

            if (ZeroKnowledgeProofValid(GB, _b, X4sV, X4sR, PartnerParticipantId) == false)
            {
                throw new CryptoException("Round 2 validation failed. Possible impersonation attempt.");
            }

            ProtocolState = State.Round2Validated;
        }
Example #3
0
        /// <summary>
        ///     Restores the state of an incomplete J-PAKE session,
        ///     given private keys and DTO objects created/received from that session.
        /// </summary>
        /// <param name="x2">Private key.</param>
        /// <param name="round1Created">Round 1 created/sent.</param>
        /// <param name="round1Received">Round 1 received.</param>
        /// <param name="round2Created">Round 2 created/sent.</param>
        /// <param name="round2Received">Round 2 received.</param>
        /// <param name="round3Created">Round 3 created/sent.</param>
        public void RestoreState(byte[] x2, ECJpakeRound1 round1Created, ECJpakeRound1 round1Received = null,
                                 ECJpakeRound2 round2Created = null, ECJpakeRound2 round2Received = null, JpakeRound3 round3Created = null)
        {
            Contract.Requires(ProtocolState == State.Initialised, "Cannot restore state of already-active protocol session!");
            Contract.Requires(round1Created != null);

            _gx1          = _domain.Curve.DecodePoint(round1Created.GX1);
            _gx2          = _domain.Curve.DecodePoint(round1Created.GX2);
            ProtocolState = State.Round1Created;

            if (round1Received != null)
            {
                if (String.IsNullOrEmpty(round1Received.ParticipantId))
                {
                    throw new ArgumentException("Partner participant ID in round 1 received is null or empty.");
                }
                PartnerParticipantId = round1Received.ParticipantId;
                _gx3          = _domain.Curve.DecodePoint(round1Received.GX1);
                _gx4          = _domain.Curve.DecodePoint(round1Received.GX2);
                ProtocolState = State.Round1Validated;
            }
            else
            {
                return;
            }

            if (round2Created != null)
            {
                ProtocolState = State.Round2Created;
            }
            else
            {
                return;
            }

            if (round2Received != null)
            {
                if (PartnerParticipantId.Equals(round2Received.ParticipantId, StringComparison.Ordinal) == false)
                {
                    throw new ArgumentException("Partner participant ID of round 2 does not match value from round 1.");
                }
                _b            = _domain.Curve.DecodePoint(round2Received.A);
                ProtocolState = State.Round2Validated;
            }
            else
            {
                return;
            }

            if (round3Created != null)
            {
                // Keying material has been calculated
                _b            = _domain.Curve.DecodePoint(round2Received.A);
                ProtocolState = State.Round3Created;
            }
            else
            {
                if (x2.IsNullOrZeroLength())
                {
                    throw new ArgumentException("Session cannot be resumed without private key x2Export. Aborting.");
                }
            }
        }