You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
4.0 KiB
107 lines
4.0 KiB
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) |
|
#pragma warning disable |
|
using System; |
|
|
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Math; |
|
|
|
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.JPake |
|
{ |
|
/// <summary> |
|
/// A pre-computed prime order group for use during a J-PAKE exchange. |
|
/// |
|
/// Typically a Schnorr group is used. In general, J-PAKE can use any prime order group |
|
/// that is suitable for public key cryptography, including elliptic curve cryptography. |
|
/// |
|
/// See JPakePrimeOrderGroups for convenient standard groups. |
|
/// |
|
/// NIST <a href="http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/DSA2_All.pdf">publishes</a> |
|
/// many groups that can be used for the desired level of security. |
|
/// </summary> |
|
public class JPakePrimeOrderGroup |
|
{ |
|
private readonly BigInteger p; |
|
private readonly BigInteger q; |
|
private readonly BigInteger g; |
|
|
|
/// <summary> |
|
/// Constructs a new JPakePrimeOrderGroup. |
|
/// |
|
/// In general, you should use one of the pre-approved groups from |
|
/// JPakePrimeOrderGroups, rather than manually constructing one. |
|
/// |
|
/// The following basic checks are performed: |
|
/// |
|
/// p-1 must be evenly divisible by q |
|
/// g must be in [2, p-1] |
|
/// g^q mod p must equal 1 |
|
/// p must be prime (within reasonably certainty) |
|
/// q must be prime (within reasonably certainty) |
|
/// |
|
/// The prime checks are performed using BigInteger#isProbablePrime(int), |
|
/// and are therefore subject to the same probability guarantees. |
|
/// |
|
/// These checks prevent trivial mistakes. |
|
/// However, due to the small uncertainties if p and q are not prime, |
|
/// advanced attacks are not prevented. |
|
/// Use it at your own risk. |
|
/// |
|
/// Throws NullReferenceException if any argument is null. Throws |
|
/// InvalidOperationException is any of the above validations fail. |
|
/// </summary> |
|
public JPakePrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g) |
|
: this(p, q, g, false) |
|
{ |
|
// Don't skip the checks on user-specified groups. |
|
} |
|
|
|
/// <summary> |
|
/// Constructor used by the pre-approved groups in JPakePrimeOrderGroups. |
|
/// These pre-approved groups can avoid the expensive checks. |
|
/// User-specified groups should not use this constructor. |
|
/// </summary> |
|
public JPakePrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g, bool skipChecks) |
|
{ |
|
JPakeUtilities.ValidateNotNull(p, "p"); |
|
JPakeUtilities.ValidateNotNull(q, "q"); |
|
JPakeUtilities.ValidateNotNull(g, "g"); |
|
|
|
if (!skipChecks) |
|
{ |
|
if (!p.Subtract(JPakeUtilities.One).Mod(q).Equals(JPakeUtilities.Zero)) |
|
throw new ArgumentException("p-1 must be evenly divisible by q"); |
|
if (g.CompareTo(BigInteger.Two) == -1 || g.CompareTo(p.Subtract(JPakeUtilities.One)) == 1) |
|
throw new ArgumentException("g must be in [2, p-1]"); |
|
if (!g.ModPow(q, p).Equals(JPakeUtilities.One)) |
|
throw new ArgumentException("g^q mod p must equal 1"); |
|
|
|
// Note these checks do not guarantee that p and q are prime. |
|
// We just have reasonable certainty that they are prime. |
|
if (!p.IsProbablePrime(20)) |
|
throw new ArgumentException("p must be prime"); |
|
if (!q.IsProbablePrime(20)) |
|
throw new ArgumentException("q must be prime"); |
|
} |
|
|
|
this.p = p; |
|
this.q = q; |
|
this.g = g; |
|
} |
|
|
|
public virtual BigInteger P |
|
{ |
|
get { return p; } |
|
} |
|
|
|
public virtual BigInteger Q |
|
{ |
|
get { return q; } |
|
} |
|
|
|
public virtual BigInteger G |
|
{ |
|
get { return g; } |
|
} |
|
} |
|
} |
|
#pragma warning restore |
|
#endif
|
|
|