/// <summary> /// Calculates and returns the key material. /// A session key must be derived from this key material using a secure key derivation function (KDF). /// The KDF used to derive the key is handled externally (i.e. not by JPakeParticipant). /// /// The keying material will be identical for each participant if and only if /// each participant's password is the same. i.e. If the participants do not /// share the same password, then each participant will derive a different key. /// Therefore, if you immediately start using a key derived from /// the keying material, then you must handle detection of incorrect keys. /// If you want to handle this detection explicitly, you can optionally perform /// rounds 3 and 4. See JPakeParticipant for details on how to execute /// rounds 3 and 4. /// /// The keying material will be in the range <tt>[0, p-1]</tt>. /// /// ValidateRound2PayloadReceived(JPakeRound2Payload) must be called prior to this method. /// /// As a side effect, the internal password array is cleared, since it is no longer needed. /// /// After execution, the State state will be STATE_KEY_CALCULATED. /// /// Throws InvalidOperationException if called prior to ValidateRound2PayloadReceived(JPakeRound2Payload), /// or if called multiple times. /// </summary> public virtual BigInteger CalculateKeyingMaterial() { if (this.state >= STATE_KEY_CALCULATED) throw new InvalidOperationException("Key already calculated for " + participantId); if (this.state < STATE_ROUND_2_VALIDATED) throw new InvalidOperationException("Round 2 payload must be validated prior to creating key for " + participantId); BigInteger s = JPakeUtilities.CalculateS(password); // Clear the password array from memory, since we don't need it anymore. // Also set the field to null as a flag to indicate that the key has already been calculated. Array.Clear(password, 0, password.Length); this.password = null; BigInteger keyingMaterial = JPakeUtilities.CalculateKeyingMaterial(p, q, gx4, x2, s, b); // Clear the ephemeral private key fields as well. // Note that we're relying on the garbage collector to do its job to clean these up. // The old objects will hang around in memory until the garbage collector destroys them. // // If the ephemeral private keys x1 and x2 are leaked, // the attacker might be able to brute-force the password. this.x1 = null; this.x2 = null; this.b = null; // Do not clear gx* yet, since those are needed by round 3. this.state = STATE_KEY_CALCULATED; return keyingMaterial; }
/// <summary> /// Creates and returns the payload to send to the other participant during round 2. /// /// ValidateRound1PayloadReceived(JPakeRound1Payload) must be called prior to this method. /// /// After execution, the State state will be STATE_ROUND_2_CREATED. /// /// Throws InvalidOperationException if called prior to ValidateRound1PayloadReceived(JPakeRound1Payload), or multiple times /// </summary> public virtual JPakeRound2Payload CreateRound2PayloadToSend() { if (this.state >= STATE_ROUND_2_CREATED) throw new InvalidOperationException("Round 2 payload already created for " + this.participantId); if (this.state < STATE_ROUND_1_VALIDATED) throw new InvalidOperationException("Round 1 payload must be validated prior to creating round 2 payload for " + this.participantId); BigInteger gA = JPakeUtilities.CalculateGA(p, gx1, gx3, gx4); BigInteger s = JPakeUtilities.CalculateS(password); BigInteger x2s = JPakeUtilities.CalculateX2s(q, x2, s); BigInteger A = JPakeUtilities.CalculateA(p, q, gA, x2s); BigInteger[] knowledgeProofForX2s = JPakeUtilities.CalculateZeroKnowledgeProof(p, q, gA, A, x2s, participantId, digest, random); this.state = STATE_ROUND_2_CREATED; return new JPakeRound2Payload(participantId, A, knowledgeProofForX2s); }
public virtual JPakeRound2Payload CreateRound2PayloadToSend() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (state >= STATE_ROUND_2_CREATED) { throw new InvalidOperationException("Round 2 payload already created for " + participantId); } if (state < STATE_ROUND_1_VALIDATED) { throw new InvalidOperationException("Round 1 payload must be validated prior to creating round 2 payload for " + participantId); } BigInteger gA = JPakeUtilities.CalculateGA(p, gx1, gx3, gx4); BigInteger s = JPakeUtilities.CalculateS(password); BigInteger bigInteger = JPakeUtilities.CalculateX2s(q, x2, s); BigInteger bigInteger2 = JPakeUtilities.CalculateA(p, q, gA, bigInteger); BigInteger[] knowledgeProofForX2s = JPakeUtilities.CalculateZeroKnowledgeProof(p, q, gA, bigInteger2, bigInteger, participantId, digest, random); state = STATE_ROUND_2_CREATED; return(new JPakeRound2Payload(participantId, bigInteger2, knowledgeProofForX2s)); }
public virtual BigInteger CalculateKeyingMaterial() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (state >= STATE_KEY_CALCULATED) { throw new InvalidOperationException("Key already calculated for " + participantId); } if (state < STATE_ROUND_2_VALIDATED) { throw new InvalidOperationException("Round 2 payload must be validated prior to creating key for " + participantId); } BigInteger s = JPakeUtilities.CalculateS(password); global::System.Array.Clear((global::System.Array)password, 0, password.Length); password = null; BigInteger result = JPakeUtilities.CalculateKeyingMaterial(p, q, gx4, x2, s, b); x1 = null; x2 = null; b = null; state = STATE_KEY_CALCULATED; return(result); }