add all
This commit is contained in:
98
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/DHAgreement.cs
vendored
Normal file
98
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/DHAgreement.cs
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Generators;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement
|
||||
{
|
||||
/**
|
||||
* a Diffie-Hellman key exchange engine.
|
||||
* <p>
|
||||
* note: This uses MTI/A0 key agreement in order to make the key agreement
|
||||
* secure against passive attacks. If you're doing Diffie-Hellman and both
|
||||
* parties have long term public keys you should look at using this. For
|
||||
* further information have a look at RFC 2631.</p>
|
||||
* <p>
|
||||
* It's possible to extend this to more than two parties as well, for the moment
|
||||
* that is left as an exercise for the reader.</p>
|
||||
*/
|
||||
public class DHAgreement
|
||||
{
|
||||
private DHPrivateKeyParameters key;
|
||||
private DHParameters dhParams;
|
||||
private BigInteger privateValue;
|
||||
private SecureRandom random;
|
||||
|
||||
public void Init(ICipherParameters parameters)
|
||||
{
|
||||
AsymmetricKeyParameter kParam;
|
||||
if (parameters is ParametersWithRandom rParam)
|
||||
{
|
||||
this.random = rParam.Random;
|
||||
kParam = (AsymmetricKeyParameter)rParam.Parameters;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.random = CryptoServicesRegistrar.GetSecureRandom();
|
||||
kParam = (AsymmetricKeyParameter)parameters;
|
||||
}
|
||||
|
||||
if (!(kParam is DHPrivateKeyParameters dhPrivateKeyParameters))
|
||||
throw new ArgumentException("DHEngine expects DHPrivateKeyParameters");
|
||||
|
||||
this.key = dhPrivateKeyParameters;
|
||||
this.dhParams = dhPrivateKeyParameters.Parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate our initial message.
|
||||
*/
|
||||
public BigInteger CalculateMessage()
|
||||
{
|
||||
DHKeyPairGenerator dhGen = new DHKeyPairGenerator();
|
||||
dhGen.Init(new DHKeyGenerationParameters(random, dhParams));
|
||||
AsymmetricCipherKeyPair dhPair = dhGen.GenerateKeyPair();
|
||||
|
||||
this.privateValue = ((DHPrivateKeyParameters)dhPair.Private).X;
|
||||
|
||||
return ((DHPublicKeyParameters)dhPair.Public).Y;
|
||||
}
|
||||
|
||||
/**
|
||||
* given a message from a given party and the corresponding public key
|
||||
* calculate the next message in the agreement sequence. In this case
|
||||
* this will represent the shared secret.
|
||||
*/
|
||||
public BigInteger CalculateAgreement(
|
||||
DHPublicKeyParameters pub,
|
||||
BigInteger message)
|
||||
{
|
||||
if (pub == null)
|
||||
throw new ArgumentNullException("pub");
|
||||
if (message == null)
|
||||
throw new ArgumentNullException("message");
|
||||
|
||||
if (!pub.Parameters.Equals(dhParams))
|
||||
throw new ArgumentException("Diffie-Hellman public key has wrong parameters.");
|
||||
|
||||
BigInteger p = dhParams.P;
|
||||
|
||||
BigInteger peerY = pub.Y;
|
||||
if (peerY == null || peerY.CompareTo(BigInteger.One) <= 0 || peerY.CompareTo(p.Subtract(BigInteger.One)) >= 0)
|
||||
throw new ArgumentException("Diffie-Hellman public key is weak");
|
||||
|
||||
BigInteger result = peerY.ModPow(privateValue, p);
|
||||
if (result.Equals(BigInteger.One))
|
||||
throw new InvalidOperationException("Shared key can't be 1");
|
||||
|
||||
return message.ModPow(key.X, p).Multiply(result).Mod(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8adac6c91a76364d9616564821b9b82
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,76 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement
|
||||
{
|
||||
/**
|
||||
* a Diffie-Hellman key agreement class.
|
||||
* <p>
|
||||
* note: This is only the basic algorithm, it doesn't take advantage of
|
||||
* long term public keys if they are available. See the DHAgreement class
|
||||
* for a "better" implementation.</p>
|
||||
*/
|
||||
public class DHBasicAgreement
|
||||
: IBasicAgreement
|
||||
{
|
||||
private DHPrivateKeyParameters key;
|
||||
private DHParameters dhParams;
|
||||
|
||||
public virtual void Init(
|
||||
ICipherParameters parameters)
|
||||
{
|
||||
if (parameters is ParametersWithRandom)
|
||||
{
|
||||
parameters = ((ParametersWithRandom) parameters).Parameters;
|
||||
}
|
||||
|
||||
if (!(parameters is DHPrivateKeyParameters))
|
||||
{
|
||||
throw new ArgumentException("DHEngine expects DHPrivateKeyParameters");
|
||||
}
|
||||
|
||||
this.key = (DHPrivateKeyParameters) parameters;
|
||||
this.dhParams = key.Parameters;
|
||||
}
|
||||
|
||||
public virtual int GetFieldSize()
|
||||
{
|
||||
return (key.Parameters.P.BitLength + 7) / 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* given a short term public key from a given party calculate the next
|
||||
* message in the agreement sequence.
|
||||
*/
|
||||
public virtual BigInteger CalculateAgreement(
|
||||
ICipherParameters pubKey)
|
||||
{
|
||||
if (this.key == null)
|
||||
throw new InvalidOperationException("Agreement algorithm not initialised");
|
||||
|
||||
DHPublicKeyParameters pub = (DHPublicKeyParameters)pubKey;
|
||||
|
||||
if (!pub.Parameters.Equals(dhParams))
|
||||
throw new ArgumentException("Diffie-Hellman public key has wrong parameters.");
|
||||
|
||||
BigInteger p = dhParams.P;
|
||||
|
||||
BigInteger peerY = pub.Y;
|
||||
if (peerY == null || peerY.CompareTo(BigInteger.One) <= 0 || peerY.CompareTo(p.Subtract(BigInteger.One)) >= 0)
|
||||
throw new ArgumentException("Diffie-Hellman public key is weak");
|
||||
|
||||
BigInteger result = peerY.ModPow(key.X, p);
|
||||
if (result.Equals(BigInteger.One))
|
||||
throw new InvalidOperationException("Shared key can't be 1");
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd6d7a6c5af7d4843b43ae13b6023d48
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
253
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/DHStandardGroups.cs
vendored
Normal file
253
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/DHStandardGroups.cs
vendored
Normal file
@@ -0,0 +1,253 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.Encoders;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement
|
||||
{
|
||||
/// <summary>Standard Diffie-Hellman groups from various IETF specifications.</summary>
|
||||
public class DHStandardGroups
|
||||
{
|
||||
private static readonly BigInteger Two = BigInteger.ValueOf(2);
|
||||
|
||||
private static BigInteger FromHex(string hex)
|
||||
{
|
||||
return new BigInteger(1, Hex.DecodeStrict(hex));
|
||||
}
|
||||
|
||||
private static DHParameters FromPG(string hexP, string hexG)
|
||||
{
|
||||
return new DHParameters(FromHex(hexP), FromHex(hexG));
|
||||
}
|
||||
|
||||
private static DHParameters SafePrimeGen2(string hexP)
|
||||
{
|
||||
return SafePrimeGen2(hexP, 0);
|
||||
}
|
||||
|
||||
private static DHParameters SafePrimeGen2(string hexP, int l)
|
||||
{
|
||||
// NOTE: A group using a safe prime (i.e. q = (p-1)/2), and generator g = 2
|
||||
BigInteger p = FromHex(hexP);
|
||||
return new DHParameters(p, Two, p.ShiftRight(1), l);
|
||||
}
|
||||
|
||||
/*
|
||||
* RFC 2409
|
||||
*/
|
||||
private static readonly string rfc2409_768_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
+ "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF";
|
||||
public static readonly DHParameters rfc2409_768 = SafePrimeGen2(rfc2409_768_p);
|
||||
|
||||
private static readonly string rfc2409_1024_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
|
||||
+ "FFFFFFFFFFFFFFFF";
|
||||
public static readonly DHParameters rfc2409_1024 = SafePrimeGen2(rfc2409_1024_p);
|
||||
|
||||
/*
|
||||
* RFC 3526
|
||||
*/
|
||||
private static readonly string rfc3526_1536_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
+ "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF";
|
||||
private static readonly int rfc3526_1536_l = 200; // RFC3526/RFC7919
|
||||
public static readonly DHParameters rfc3526_1536 = SafePrimeGen2(rfc3526_1536_p, rfc3526_1536_l);
|
||||
|
||||
private static readonly string rfc3526_2048_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
|
||||
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AACAA68FFFFFFFFFFFFFFFF";
|
||||
private static readonly int rfc3526_2048_l = System.Math.Max(225, 112 * 2); // MAX(RFC3526/RFC7919,FIPS)
|
||||
public static readonly DHParameters rfc3526_2048 = SafePrimeGen2(rfc3526_2048_p, rfc3526_2048_l);
|
||||
|
||||
private static readonly string rfc3526_3072_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
|
||||
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
|
||||
+ "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
|
||||
+ "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
|
||||
+ "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF";
|
||||
private static readonly int rfc3526_3072_l = System.Math.Max(275, 128 * 2); // MAX(RFC3526/RFC7919,FIPS)
|
||||
public static readonly DHParameters rfc3526_3072 = SafePrimeGen2(rfc3526_3072_p, rfc3526_3072_l);
|
||||
|
||||
private static readonly string rfc3526_4096_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
|
||||
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
|
||||
+ "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
|
||||
+ "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
|
||||
+ "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
|
||||
+ "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
|
||||
+ "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199"
|
||||
+ "FFFFFFFFFFFFFFFF";
|
||||
private static readonly int rfc3526_4096_l = System.Math.Max(325, 152 * 2); // MAX(RFC3526/RFC7919,FIPS)
|
||||
public static readonly DHParameters rfc3526_4096 = SafePrimeGen2(rfc3526_4096_p, rfc3526_4096_l);
|
||||
|
||||
private static readonly string rfc3526_6144_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
|
||||
+ "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
|
||||
+ "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
|
||||
+ "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
|
||||
+ "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8"
|
||||
+ "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C"
|
||||
+ "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"
|
||||
+ "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D"
|
||||
+ "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D"
|
||||
+ "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226"
|
||||
+ "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
|
||||
+ "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC"
|
||||
+ "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26"
|
||||
+ "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB"
|
||||
+ "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2"
|
||||
+ "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127"
|
||||
+ "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
|
||||
+ "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406"
|
||||
+ "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918"
|
||||
+ "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151"
|
||||
+ "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03"
|
||||
+ "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F"
|
||||
+ "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
|
||||
+ "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B"
|
||||
+ "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632"
|
||||
+ "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E"
|
||||
+ "6DCC4024FFFFFFFFFFFFFFFF";
|
||||
private static readonly int rfc3526_6144_l = System.Math.Max(375, 176 * 2); // MAX(RFC3526/RFC7919,FIPS)
|
||||
public static readonly DHParameters rfc3526_6144 = SafePrimeGen2(rfc3526_6144_p, rfc3526_6144_l);
|
||||
|
||||
private static readonly string rfc3526_8192_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
|
||||
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
|
||||
+ "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
|
||||
+ "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
|
||||
+ "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
|
||||
+ "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
|
||||
+ "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
|
||||
+ "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" + "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
|
||||
+ "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" + "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
|
||||
+ "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" + "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
|
||||
+ "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
|
||||
+ "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" + "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
|
||||
+ "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" + "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300"
|
||||
+ "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" + "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9"
|
||||
+ "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" + "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A"
|
||||
+ "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" + "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1"
|
||||
+ "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" + "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47"
|
||||
+ "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" + "60C980DD98EDD3DFFFFFFFFFFFFFFFFF";
|
||||
private static readonly int rfc3526_8192_l = System.Math.Max(400, 200 * 2); // MAX(RFC3526/RFC7919,FIPS)
|
||||
public static readonly DHParameters rfc3526_8192 = SafePrimeGen2(rfc3526_8192_p, rfc3526_8192_l);
|
||||
|
||||
/*
|
||||
* RFC 4306
|
||||
*/
|
||||
public static readonly DHParameters rfc4306_768 = rfc2409_768;
|
||||
public static readonly DHParameters rfc4306_1024 = rfc2409_1024;
|
||||
|
||||
/*
|
||||
* RFC 5996
|
||||
*/
|
||||
public static readonly DHParameters rfc5996_768 = rfc4306_768;
|
||||
public static readonly DHParameters rfc5996_1024 = rfc4306_1024;
|
||||
|
||||
/*
|
||||
* RFC 7919
|
||||
*/
|
||||
private static readonly string rfc7919_ffdhe2048_p = "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1"
|
||||
+ "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" + "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561"
|
||||
+ "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" + "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735"
|
||||
+ "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" + "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19"
|
||||
+ "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" + "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73"
|
||||
+ "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" + "886B423861285C97FFFFFFFFFFFFFFFF";
|
||||
private static readonly int rfc7919_ffdhe2048_l = System.Math.Max(225, 112 * 2); // MAX(RFC7919,FIPS)
|
||||
public static readonly DHParameters rfc7919_ffdhe2048 = SafePrimeGen2(rfc7919_ffdhe2048_p, rfc7919_ffdhe2048_l);
|
||||
|
||||
private static readonly string rfc7919_ffdhe3072_p = "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1"
|
||||
+ "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" + "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561"
|
||||
+ "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" + "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735"
|
||||
+ "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" + "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19"
|
||||
+ "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" + "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73"
|
||||
+ "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" + "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238"
|
||||
+ "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" + "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3"
|
||||
+ "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" + "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF"
|
||||
+ "3C1B20EE3FD59D7C25E41D2B66C62E37FFFFFFFFFFFFFFFF";
|
||||
private static readonly int rfc7919_ffdhe3072_l = System.Math.Max(275, 128 * 2); // MAX(RFC7919,FIPS)
|
||||
public static readonly DHParameters rfc7919_ffdhe3072 = SafePrimeGen2(rfc7919_ffdhe3072_p, rfc7919_ffdhe3072_l);
|
||||
|
||||
private static readonly string rfc7919_ffdhe4096_p = "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1"
|
||||
+ "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" + "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561"
|
||||
+ "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" + "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735"
|
||||
+ "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" + "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19"
|
||||
+ "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" + "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73"
|
||||
+ "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" + "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238"
|
||||
+ "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" + "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3"
|
||||
+ "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" + "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF"
|
||||
+ "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" + "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004"
|
||||
+ "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" + "A907600A918130C46DC778F971AD0038092999A333CB8B7A"
|
||||
+ "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" + "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E655F6A"
|
||||
+ "FFFFFFFFFFFFFFFF";
|
||||
private static readonly int rfc7919_ffdhe4096_l = System.Math.Max(325, 152 * 2); // MAX(RFC7919,FIPS)
|
||||
public static readonly DHParameters rfc7919_ffdhe4096 = SafePrimeGen2(rfc7919_ffdhe4096_p, rfc7919_ffdhe4096_l);
|
||||
|
||||
private static readonly string rfc7919_ffdhe6144_p = "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1"
|
||||
+ "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" + "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561"
|
||||
+ "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" + "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735"
|
||||
+ "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" + "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19"
|
||||
+ "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" + "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73"
|
||||
+ "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" + "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238"
|
||||
+ "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" + "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3"
|
||||
+ "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" + "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF"
|
||||
+ "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" + "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004"
|
||||
+ "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" + "A907600A918130C46DC778F971AD0038092999A333CB8B7A"
|
||||
+ "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" + "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD902"
|
||||
+ "0BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA6" + "3BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3A"
|
||||
+ "CDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477" + "A52471F7A9A96910B855322EDB6340D8A00EF092350511E3"
|
||||
+ "0ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4" + "763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6"
|
||||
+ "B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538C" + "D72B03746AE77F5E62292C311562A846505DC82DB854338A"
|
||||
+ "E49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B04" + "5B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1"
|
||||
+ "A41D570D7938DAD4A40E329CD0E40E65FFFFFFFFFFFFFFFF";
|
||||
private static readonly int rfc7919_ffdhe6144_l = System.Math.Max(375, 176 * 2); // MAX(RFC7919,FIPS)
|
||||
public static readonly DHParameters rfc7919_ffdhe6144 = SafePrimeGen2(rfc7919_ffdhe6144_p, rfc7919_ffdhe6144_l);
|
||||
|
||||
private static readonly string rfc7919_ffdhe8192_p = "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1"
|
||||
+ "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" + "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561"
|
||||
+ "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" + "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735"
|
||||
+ "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" + "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19"
|
||||
+ "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" + "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73"
|
||||
+ "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" + "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238"
|
||||
+ "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" + "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3"
|
||||
+ "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" + "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF"
|
||||
+ "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" + "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004"
|
||||
+ "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" + "A907600A918130C46DC778F971AD0038092999A333CB8B7A"
|
||||
+ "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" + "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD902"
|
||||
+ "0BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA6" + "3BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3A"
|
||||
+ "CDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477" + "A52471F7A9A96910B855322EDB6340D8A00EF092350511E3"
|
||||
+ "0ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4" + "763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6"
|
||||
+ "B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538C" + "D72B03746AE77F5E62292C311562A846505DC82DB854338A"
|
||||
+ "E49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B04" + "5B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1"
|
||||
+ "A41D570D7938DAD4A40E329CCFF46AAA36AD004CF600C838" + "1E425A31D951AE64FDB23FCEC9509D43687FEB69EDD1CC5E"
|
||||
+ "0B8CC3BDF64B10EF86B63142A3AB8829555B2F747C932665" + "CB2C0F1CC01BD70229388839D2AF05E454504AC78B758282"
|
||||
+ "2846C0BA35C35F5C59160CC046FD8251541FC68C9C86B022" + "BB7099876A460E7451A8A93109703FEE1C217E6C3826E52C"
|
||||
+ "51AA691E0E423CFC99E9E31650C1217B624816CDAD9A95F9" + "D5B8019488D9C0A0A1FE3075A577E23183F81D4A3F2FA457"
|
||||
+ "1EFC8CE0BA8A4FE8B6855DFE72B0A66EDED2FBABFBE58A30" + "FAFABE1C5D71A87E2F741EF8C1FE86FEA6BBFDE530677F0D"
|
||||
+ "97D11D49F7A8443D0822E506A9F4614E011E2A94838FF88C" + "D68C8BB7C5C6424CFFFFFFFFFFFFFFFF";
|
||||
private static readonly int rfc7919_ffdhe8192_l = System.Math.Max(400, 200 * 2); // MAX(RFC7919,FIPS)
|
||||
public static readonly DHParameters rfc7919_ffdhe8192 = SafePrimeGen2(rfc7919_ffdhe8192_p, rfc7919_ffdhe8192_l);
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0dec6331289142946bbcb9e8889a4e76
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,78 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math.EC;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement
|
||||
{
|
||||
/**
|
||||
* P1363 7.2.1 ECSVDP-DH
|
||||
*
|
||||
* ECSVDP-DH is Elliptic Curve Secret Value Derivation Primitive,
|
||||
* Diffie-Hellman version. It is based on the work of [DH76], [Mil86],
|
||||
* and [Kob87]. This primitive derives a shared secret value from one
|
||||
* party's private key and another party's public key, where both have
|
||||
* the same set of EC domain parameters. If two parties correctly
|
||||
* execute this primitive, they will produce the same output. This
|
||||
* primitive can be invoked by a scheme to derive a shared secret key;
|
||||
* specifically, it may be used with the schemes ECKAS-DH1 and
|
||||
* DL/ECKAS-DH2. It assumes that the input keys are valid (see also
|
||||
* Section 7.2.2).
|
||||
*/
|
||||
public class ECDHBasicAgreement
|
||||
: IBasicAgreement
|
||||
{
|
||||
protected internal ECPrivateKeyParameters privKey;
|
||||
|
||||
public virtual void Init(
|
||||
ICipherParameters parameters)
|
||||
{
|
||||
if (parameters is ParametersWithRandom)
|
||||
{
|
||||
parameters = ((ParametersWithRandom)parameters).Parameters;
|
||||
}
|
||||
|
||||
this.privKey = (ECPrivateKeyParameters)parameters;
|
||||
}
|
||||
|
||||
public virtual int GetFieldSize()
|
||||
{
|
||||
return (privKey.Parameters.Curve.FieldSize + 7) / 8;
|
||||
}
|
||||
|
||||
public virtual BigInteger CalculateAgreement(
|
||||
ICipherParameters pubKey)
|
||||
{
|
||||
ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey;
|
||||
ECDomainParameters dp = privKey.Parameters;
|
||||
if (!dp.Equals(pub.Parameters))
|
||||
throw new InvalidOperationException("ECDH public key has wrong domain parameters");
|
||||
|
||||
BigInteger d = privKey.D;
|
||||
|
||||
// Always perform calculations on the exact curve specified by our private key's parameters
|
||||
ECPoint Q = ECAlgorithms.CleanPoint(dp.Curve, pub.Q);
|
||||
if (Q.IsInfinity)
|
||||
throw new InvalidOperationException("Infinity is not a valid public key for ECDH");
|
||||
|
||||
BigInteger h = dp.H;
|
||||
if (!h.Equals(BigInteger.One))
|
||||
{
|
||||
d = dp.HInv.Multiply(d).Mod(dp.N);
|
||||
Q = ECAlgorithms.ReferenceMultiply(Q, h);
|
||||
}
|
||||
|
||||
ECPoint P = Q.Multiply(d).Normalize();
|
||||
if (P.IsInfinity)
|
||||
throw new InvalidOperationException("Infinity is not a valid agreement value for ECDH");
|
||||
|
||||
return P.AffineXCoord.ToBigInteger();
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e166bf1506f59b24b85938755856b0c1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,76 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math.EC;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement
|
||||
{
|
||||
/**
|
||||
* P1363 7.2.2 ECSVDP-DHC
|
||||
*
|
||||
* ECSVDP-DHC is Elliptic Curve Secret Value Derivation Primitive,
|
||||
* Diffie-Hellman version with cofactor multiplication. It is based on
|
||||
* the work of [DH76], [Mil86], [Kob87], [LMQ98] and [Kal98a]. This
|
||||
* primitive derives a shared secret value from one party's private key
|
||||
* and another party's public key, where both have the same set of EC
|
||||
* domain parameters. If two parties correctly execute this primitive,
|
||||
* they will produce the same output. This primitive can be invoked by a
|
||||
* scheme to derive a shared secret key; specifically, it may be used
|
||||
* with the schemes ECKAS-DH1 and DL/ECKAS-DH2. It does not assume the
|
||||
* validity of the input public key (see also Section 7.2.1).
|
||||
* <p>
|
||||
* Note: As stated P1363 compatibility mode with ECDH can be preset, and
|
||||
* in this case the implementation doesn't have a ECDH compatibility mode
|
||||
* (if you want that just use ECDHBasicAgreement and note they both implement
|
||||
* BasicAgreement!).</p>
|
||||
*/
|
||||
public class ECDHCBasicAgreement
|
||||
: IBasicAgreement
|
||||
{
|
||||
private ECPrivateKeyParameters privKey;
|
||||
|
||||
public virtual void Init(
|
||||
ICipherParameters parameters)
|
||||
{
|
||||
if (parameters is ParametersWithRandom)
|
||||
{
|
||||
parameters = ((ParametersWithRandom) parameters).Parameters;
|
||||
}
|
||||
|
||||
this.privKey = (ECPrivateKeyParameters)parameters;
|
||||
}
|
||||
|
||||
public virtual int GetFieldSize()
|
||||
{
|
||||
return (privKey.Parameters.Curve.FieldSize + 7) / 8;
|
||||
}
|
||||
|
||||
public virtual BigInteger CalculateAgreement(
|
||||
ICipherParameters pubKey)
|
||||
{
|
||||
ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey;
|
||||
ECDomainParameters dp = privKey.Parameters;
|
||||
if (!dp.Equals(pub.Parameters))
|
||||
throw new InvalidOperationException("ECDHC public key has wrong domain parameters");
|
||||
|
||||
BigInteger hd = dp.H.Multiply(privKey.D).Mod(dp.N);
|
||||
|
||||
// Always perform calculations on the exact curve specified by our private key's parameters
|
||||
ECPoint pubPoint = ECAlgorithms.CleanPoint(dp.Curve, pub.Q);
|
||||
if (pubPoint.IsInfinity)
|
||||
throw new InvalidOperationException("Infinity is not a valid public key for ECDHC");
|
||||
|
||||
ECPoint P = pubPoint.Multiply(hd).Normalize();
|
||||
if (P.IsInfinity)
|
||||
throw new InvalidOperationException("Infinity is not a valid agreement value for ECDHC");
|
||||
|
||||
return P.AffineXCoord.ToBigInteger();
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c04de26174e51c4981fd8ee28380d6f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,63 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.X9;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.Kdf;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement
|
||||
{
|
||||
public class ECDHWithKdfBasicAgreement
|
||||
: ECDHBasicAgreement
|
||||
{
|
||||
private readonly string algorithm;
|
||||
private readonly IDerivationFunction kdf;
|
||||
|
||||
public ECDHWithKdfBasicAgreement(
|
||||
string algorithm,
|
||||
IDerivationFunction kdf)
|
||||
{
|
||||
if (algorithm == null)
|
||||
throw new ArgumentNullException("algorithm");
|
||||
if (kdf == null)
|
||||
throw new ArgumentNullException("kdf");
|
||||
|
||||
this.algorithm = algorithm;
|
||||
this.kdf = kdf;
|
||||
}
|
||||
|
||||
public override BigInteger CalculateAgreement(
|
||||
ICipherParameters pubKey)
|
||||
{
|
||||
// Note that the ec.KeyAgreement class in JCE only uses kdf in one
|
||||
// of the engineGenerateSecret methods.
|
||||
|
||||
BigInteger result = base.CalculateAgreement(pubKey);
|
||||
|
||||
int keySize = GeneratorUtilities.GetDefaultKeySize(algorithm);
|
||||
|
||||
DHKdfParameters dhKdfParams = new DHKdfParameters(
|
||||
new DerObjectIdentifier(algorithm),
|
||||
keySize,
|
||||
BigIntToBytes(result));
|
||||
|
||||
kdf.Init(dhKdfParams);
|
||||
|
||||
byte[] keyBytes = new byte[keySize / 8];
|
||||
kdf.GenerateBytes(keyBytes, 0, keyBytes.Length);
|
||||
|
||||
return new BigInteger(1, keyBytes);
|
||||
}
|
||||
|
||||
private byte[] BigIntToBytes(BigInteger r)
|
||||
{
|
||||
int byteLength = X9IntegerConverter.GetByteLength(privKey.Parameters.Curve);
|
||||
return X9IntegerConverter.IntegerToBytes(r, byteLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b758c6f1e001e8f42965f87ad5648014
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,90 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math.EC;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement
|
||||
{
|
||||
public class ECMqvBasicAgreement
|
||||
: IBasicAgreement
|
||||
{
|
||||
protected internal MqvPrivateParameters privParams;
|
||||
|
||||
public virtual void Init(
|
||||
ICipherParameters parameters)
|
||||
{
|
||||
if (parameters is ParametersWithRandom)
|
||||
{
|
||||
parameters = ((ParametersWithRandom)parameters).Parameters;
|
||||
}
|
||||
|
||||
this.privParams = (MqvPrivateParameters)parameters;
|
||||
}
|
||||
|
||||
public virtual int GetFieldSize()
|
||||
{
|
||||
return (privParams.StaticPrivateKey.Parameters.Curve.FieldSize + 7) / 8;
|
||||
}
|
||||
|
||||
public virtual BigInteger CalculateAgreement(
|
||||
ICipherParameters pubKey)
|
||||
{
|
||||
MqvPublicParameters pubParams = (MqvPublicParameters)pubKey;
|
||||
|
||||
ECPrivateKeyParameters staticPrivateKey = privParams.StaticPrivateKey;
|
||||
ECDomainParameters parameters = staticPrivateKey.Parameters;
|
||||
|
||||
if (!parameters.Equals(pubParams.StaticPublicKey.Parameters))
|
||||
throw new InvalidOperationException("ECMQV public key components have wrong domain parameters");
|
||||
|
||||
ECPoint agreement = CalculateMqvAgreement(parameters, staticPrivateKey,
|
||||
privParams.EphemeralPrivateKey, privParams.EphemeralPublicKey,
|
||||
pubParams.StaticPublicKey, pubParams.EphemeralPublicKey).Normalize();
|
||||
|
||||
if (agreement.IsInfinity)
|
||||
throw new InvalidOperationException("Infinity is not a valid agreement value for MQV");
|
||||
|
||||
return agreement.AffineXCoord.ToBigInteger();
|
||||
}
|
||||
|
||||
// The ECMQV Primitive as described in SEC-1, 3.4
|
||||
private static ECPoint CalculateMqvAgreement(
|
||||
ECDomainParameters parameters,
|
||||
ECPrivateKeyParameters d1U,
|
||||
ECPrivateKeyParameters d2U,
|
||||
ECPublicKeyParameters Q2U,
|
||||
ECPublicKeyParameters Q1V,
|
||||
ECPublicKeyParameters Q2V)
|
||||
{
|
||||
BigInteger n = parameters.N;
|
||||
int e = (n.BitLength + 1) / 2;
|
||||
BigInteger powE = BigInteger.One.ShiftLeft(e);
|
||||
|
||||
ECCurve curve = parameters.Curve;
|
||||
|
||||
ECPoint q2u = ECAlgorithms.CleanPoint(curve, Q2U.Q);
|
||||
ECPoint q1v = ECAlgorithms.CleanPoint(curve, Q1V.Q);
|
||||
ECPoint q2v = ECAlgorithms.CleanPoint(curve, Q2V.Q);
|
||||
|
||||
BigInteger x = q2u.AffineXCoord.ToBigInteger();
|
||||
BigInteger xBar = x.Mod(powE);
|
||||
BigInteger Q2UBar = xBar.SetBit(e);
|
||||
BigInteger s = d1U.D.Multiply(Q2UBar).Add(d2U.D).Mod(n);
|
||||
|
||||
BigInteger xPrime = q2v.AffineXCoord.ToBigInteger();
|
||||
BigInteger xPrimeBar = xPrime.Mod(powE);
|
||||
BigInteger Q2VBar = xPrimeBar.SetBit(e);
|
||||
|
||||
BigInteger hs = parameters.H.Multiply(s).Mod(n);
|
||||
|
||||
return ECAlgorithms.SumOfTwoMultiplies(
|
||||
q1v, Q2VBar.Multiply(hs).Mod(n), q2v, hs);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8724404ca73f874eb3e58672f8d7059
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,63 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.X9;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.Kdf;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement
|
||||
{
|
||||
public class ECMqvWithKdfBasicAgreement
|
||||
: ECMqvBasicAgreement
|
||||
{
|
||||
private readonly string algorithm;
|
||||
private readonly IDerivationFunction kdf;
|
||||
|
||||
public ECMqvWithKdfBasicAgreement(
|
||||
string algorithm,
|
||||
IDerivationFunction kdf)
|
||||
{
|
||||
if (algorithm == null)
|
||||
throw new ArgumentNullException("algorithm");
|
||||
if (kdf == null)
|
||||
throw new ArgumentNullException("kdf");
|
||||
|
||||
this.algorithm = algorithm;
|
||||
this.kdf = kdf;
|
||||
}
|
||||
|
||||
public override BigInteger CalculateAgreement(
|
||||
ICipherParameters pubKey)
|
||||
{
|
||||
// Note that the ec.KeyAgreement class in JCE only uses kdf in one
|
||||
// of the engineGenerateSecret methods.
|
||||
|
||||
BigInteger result = base.CalculateAgreement(pubKey);
|
||||
|
||||
int keySize = GeneratorUtilities.GetDefaultKeySize(algorithm);
|
||||
|
||||
DHKdfParameters dhKdfParams = new DHKdfParameters(
|
||||
new DerObjectIdentifier(algorithm),
|
||||
keySize,
|
||||
BigIntToBytes(result));
|
||||
|
||||
kdf.Init(dhKdfParams);
|
||||
|
||||
byte[] keyBytes = new byte[keySize / 8];
|
||||
kdf.GenerateBytes(keyBytes, 0, keyBytes.Length);
|
||||
|
||||
return new BigInteger(1, keyBytes);
|
||||
}
|
||||
|
||||
private byte[] BigIntToBytes(BigInteger r)
|
||||
{
|
||||
int byteLength = X9IntegerConverter.GetByteLength(privParams.StaticPrivateKey.Parameters.Curve);
|
||||
return X9IntegerConverter.IntegerToBytes(r, byteLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8760aeb27a3a3a4196a76b9b928cc97
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
278
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/SM2KeyExchange.cs
vendored
Normal file
278
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/SM2KeyExchange.cs
vendored
Normal file
@@ -0,0 +1,278 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Digests;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math.EC;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement
|
||||
{
|
||||
/// <summary>
|
||||
/// SM2 Key Exchange protocol - based on https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02
|
||||
/// </summary>
|
||||
public class SM2KeyExchange
|
||||
{
|
||||
private readonly IDigest mDigest;
|
||||
|
||||
private byte[] mUserID;
|
||||
private ECPrivateKeyParameters mStaticKey;
|
||||
private ECPoint mStaticPubPoint;
|
||||
private ECPoint mEphemeralPubPoint;
|
||||
private ECDomainParameters mECParams;
|
||||
private int mW;
|
||||
private ECPrivateKeyParameters mEphemeralKey;
|
||||
private bool mInitiator;
|
||||
|
||||
public SM2KeyExchange()
|
||||
: this(new SM3Digest())
|
||||
{
|
||||
}
|
||||
|
||||
public SM2KeyExchange(IDigest digest)
|
||||
{
|
||||
this.mDigest = digest;
|
||||
}
|
||||
|
||||
public virtual void Init(ICipherParameters privParam)
|
||||
{
|
||||
SM2KeyExchangePrivateParameters baseParam;
|
||||
|
||||
if (privParam is ParametersWithID)
|
||||
{
|
||||
baseParam = (SM2KeyExchangePrivateParameters)((ParametersWithID)privParam).Parameters;
|
||||
mUserID = ((ParametersWithID)privParam).GetID();
|
||||
}
|
||||
else
|
||||
{
|
||||
baseParam = (SM2KeyExchangePrivateParameters)privParam;
|
||||
mUserID = new byte[0];
|
||||
}
|
||||
|
||||
mInitiator = baseParam.IsInitiator;
|
||||
mStaticKey = baseParam.StaticPrivateKey;
|
||||
mEphemeralKey = baseParam.EphemeralPrivateKey;
|
||||
mECParams = mStaticKey.Parameters;
|
||||
mStaticPubPoint = baseParam.StaticPublicPoint;
|
||||
mEphemeralPubPoint = baseParam.EphemeralPublicPoint;
|
||||
mW = mECParams.Curve.FieldSize / 2 - 1;
|
||||
}
|
||||
|
||||
public virtual byte[] CalculateKey(int kLen, ICipherParameters pubParam)
|
||||
{
|
||||
SM2KeyExchangePublicParameters otherPub;
|
||||
byte[] otherUserID;
|
||||
|
||||
if (pubParam is ParametersWithID)
|
||||
{
|
||||
otherPub = (SM2KeyExchangePublicParameters)((ParametersWithID)pubParam).Parameters;
|
||||
otherUserID = ((ParametersWithID)pubParam).GetID();
|
||||
}
|
||||
else
|
||||
{
|
||||
otherPub = (SM2KeyExchangePublicParameters)pubParam;
|
||||
otherUserID = new byte[0];
|
||||
}
|
||||
|
||||
byte[] za = GetZ(mDigest, mUserID, mStaticPubPoint);
|
||||
byte[] zb = GetZ(mDigest, otherUserID, otherPub.StaticPublicKey.Q);
|
||||
|
||||
ECPoint U = CalculateU(otherPub);
|
||||
|
||||
byte[] rv;
|
||||
if (mInitiator)
|
||||
{
|
||||
rv = Kdf(U, za, zb, kLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = Kdf(U, zb, za, kLen);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
public virtual byte[][] CalculateKeyWithConfirmation(int kLen, byte[] confirmationTag, ICipherParameters pubParam)
|
||||
{
|
||||
SM2KeyExchangePublicParameters otherPub;
|
||||
byte[] otherUserID;
|
||||
|
||||
if (pubParam is ParametersWithID)
|
||||
{
|
||||
otherPub = (SM2KeyExchangePublicParameters)((ParametersWithID)pubParam).Parameters;
|
||||
otherUserID = ((ParametersWithID)pubParam).GetID();
|
||||
}
|
||||
else
|
||||
{
|
||||
otherPub = (SM2KeyExchangePublicParameters)pubParam;
|
||||
otherUserID = new byte[0];
|
||||
}
|
||||
|
||||
if (mInitiator && confirmationTag == null)
|
||||
throw new ArgumentException("if initiating, confirmationTag must be set");
|
||||
|
||||
byte[] za = GetZ(mDigest, mUserID, mStaticPubPoint);
|
||||
byte[] zb = GetZ(mDigest, otherUserID, otherPub.StaticPublicKey.Q);
|
||||
|
||||
ECPoint U = CalculateU(otherPub);
|
||||
|
||||
byte[] rv;
|
||||
if (mInitiator)
|
||||
{
|
||||
rv = Kdf(U, za, zb, kLen);
|
||||
|
||||
byte[] inner = CalculateInnerHash(mDigest, U, za, zb, mEphemeralPubPoint, otherPub.EphemeralPublicKey.Q);
|
||||
|
||||
byte[] s1 = S1(mDigest, U, inner);
|
||||
|
||||
if (!Arrays.ConstantTimeAreEqual(s1, confirmationTag))
|
||||
throw new InvalidOperationException("confirmation tag mismatch");
|
||||
|
||||
return new byte[][] { rv, S2(mDigest, U, inner)};
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = Kdf(U, zb, za, kLen);
|
||||
|
||||
byte[] inner = CalculateInnerHash(mDigest, U, zb, za, otherPub.EphemeralPublicKey.Q, mEphemeralPubPoint);
|
||||
|
||||
return new byte[][] { rv, S1(mDigest, U, inner), S2(mDigest, U, inner) };
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual ECPoint CalculateU(SM2KeyExchangePublicParameters otherPub)
|
||||
{
|
||||
ECDomainParameters dp = mStaticKey.Parameters;
|
||||
|
||||
ECPoint p1 = ECAlgorithms.CleanPoint(dp.Curve, otherPub.StaticPublicKey.Q);
|
||||
ECPoint p2 = ECAlgorithms.CleanPoint(dp.Curve, otherPub.EphemeralPublicKey.Q);
|
||||
|
||||
BigInteger x1 = Reduce(mEphemeralPubPoint.AffineXCoord.ToBigInteger());
|
||||
BigInteger x2 = Reduce(p2.AffineXCoord.ToBigInteger());
|
||||
BigInteger tA = mStaticKey.D.Add(x1.Multiply(mEphemeralKey.D));
|
||||
BigInteger k1 = mECParams.H.Multiply(tA).Mod(mECParams.N);
|
||||
BigInteger k2 = k1.Multiply(x2).Mod(mECParams.N);
|
||||
|
||||
return ECAlgorithms.SumOfTwoMultiplies(p1, k1, p2, k2).Normalize();
|
||||
}
|
||||
|
||||
protected virtual byte[] Kdf(ECPoint u, byte[] za, byte[] zb, int klen)
|
||||
{
|
||||
int digestSize = mDigest.GetDigestSize();
|
||||
byte[] buf = new byte[System.Math.Max(4, digestSize)];
|
||||
byte[] rv = new byte[(klen + 7) / 8];
|
||||
int off = 0;
|
||||
|
||||
IMemoable memo = mDigest as IMemoable;
|
||||
IMemoable copy = null;
|
||||
|
||||
if (memo != null)
|
||||
{
|
||||
AddFieldElement(mDigest, u.AffineXCoord);
|
||||
AddFieldElement(mDigest, u.AffineYCoord);
|
||||
mDigest.BlockUpdate(za, 0, za.Length);
|
||||
mDigest.BlockUpdate(zb, 0, zb.Length);
|
||||
copy = memo.Copy();
|
||||
}
|
||||
|
||||
uint ct = 0;
|
||||
|
||||
while (off < rv.Length)
|
||||
{
|
||||
if (memo != null)
|
||||
{
|
||||
memo.Reset(copy);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddFieldElement(mDigest, u.AffineXCoord);
|
||||
AddFieldElement(mDigest, u.AffineYCoord);
|
||||
mDigest.BlockUpdate(za, 0, za.Length);
|
||||
mDigest.BlockUpdate(zb, 0, zb.Length);
|
||||
}
|
||||
|
||||
Pack.UInt32_To_BE(++ct, buf, 0);
|
||||
mDigest.BlockUpdate(buf, 0, 4);
|
||||
mDigest.DoFinal(buf, 0);
|
||||
|
||||
int copyLen = System.Math.Min(digestSize, rv.Length - off);
|
||||
Array.Copy(buf, 0, rv, off, copyLen);
|
||||
off += copyLen;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
//x1~=2^w+(x1 AND (2^w-1))
|
||||
private BigInteger Reduce(BigInteger x)
|
||||
{
|
||||
return x.And(BigInteger.One.ShiftLeft(mW).Subtract(BigInteger.One)).SetBit(mW);
|
||||
}
|
||||
|
||||
private byte[] S1(IDigest digest, ECPoint u, byte[] inner)
|
||||
{
|
||||
digest.Update((byte)0x02);
|
||||
AddFieldElement(digest, u.AffineYCoord);
|
||||
digest.BlockUpdate(inner, 0, inner.Length);
|
||||
|
||||
return DigestUtilities.DoFinal(digest);
|
||||
}
|
||||
|
||||
private byte[] CalculateInnerHash(IDigest digest, ECPoint u, byte[] za, byte[] zb, ECPoint p1, ECPoint p2)
|
||||
{
|
||||
AddFieldElement(digest, u.AffineXCoord);
|
||||
digest.BlockUpdate(za, 0, za.Length);
|
||||
digest.BlockUpdate(zb, 0, zb.Length);
|
||||
AddFieldElement(digest, p1.AffineXCoord);
|
||||
AddFieldElement(digest, p1.AffineYCoord);
|
||||
AddFieldElement(digest, p2.AffineXCoord);
|
||||
AddFieldElement(digest, p2.AffineYCoord);
|
||||
|
||||
return DigestUtilities.DoFinal(digest);
|
||||
}
|
||||
|
||||
private byte[] S2(IDigest digest, ECPoint u, byte[] inner)
|
||||
{
|
||||
digest.Update((byte)0x03);
|
||||
AddFieldElement(digest, u.AffineYCoord);
|
||||
digest.BlockUpdate(inner, 0, inner.Length);
|
||||
|
||||
return DigestUtilities.DoFinal(digest);
|
||||
}
|
||||
|
||||
private byte[] GetZ(IDigest digest, byte[] userID, ECPoint pubPoint)
|
||||
{
|
||||
AddUserID(digest, userID);
|
||||
|
||||
AddFieldElement(digest, mECParams.Curve.A);
|
||||
AddFieldElement(digest, mECParams.Curve.B);
|
||||
AddFieldElement(digest, mECParams.G.AffineXCoord);
|
||||
AddFieldElement(digest, mECParams.G.AffineYCoord);
|
||||
AddFieldElement(digest, pubPoint.AffineXCoord);
|
||||
AddFieldElement(digest, pubPoint.AffineYCoord);
|
||||
|
||||
return DigestUtilities.DoFinal(digest);
|
||||
}
|
||||
|
||||
private void AddUserID(IDigest digest, byte[] userID)
|
||||
{
|
||||
uint len = (uint)(userID.Length * 8);
|
||||
|
||||
digest.Update((byte)(len >> 8));
|
||||
digest.Update((byte)len);
|
||||
digest.BlockUpdate(userID, 0, userID.Length);
|
||||
}
|
||||
|
||||
private void AddFieldElement(IDigest digest, ECFieldElement v)
|
||||
{
|
||||
byte[] p = v.GetEncoded();
|
||||
digest.BlockUpdate(p, 0, p.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 118adaca026b05a44a9842f407f1e076
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
42
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/X25519Agreement.cs
vendored
Normal file
42
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/X25519Agreement.cs
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement
|
||||
{
|
||||
public sealed class X25519Agreement
|
||||
: IRawAgreement
|
||||
{
|
||||
private X25519PrivateKeyParameters m_privateKey;
|
||||
|
||||
public void Init(ICipherParameters parameters)
|
||||
{
|
||||
m_privateKey = (X25519PrivateKeyParameters)parameters;
|
||||
}
|
||||
|
||||
public int AgreementSize
|
||||
{
|
||||
get { return X25519PrivateKeyParameters.SecretSize; }
|
||||
}
|
||||
|
||||
public void CalculateAgreement(ICipherParameters publicKey, byte[] buf, int off)
|
||||
{
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
CalculateAgreement(publicKey, buf.AsSpan(off));
|
||||
#else
|
||||
m_privateKey.GenerateSecret((X25519PublicKeyParameters)publicKey, buf, off);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public void CalculateAgreement(ICipherParameters publicKey, Span<byte> buf)
|
||||
{
|
||||
m_privateKey.GenerateSecret((X25519PublicKeyParameters)publicKey, buf);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5273366d612f0746be590ece68e701c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
42
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/X448Agreement.cs
vendored
Normal file
42
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/X448Agreement.cs
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement
|
||||
{
|
||||
public sealed class X448Agreement
|
||||
: IRawAgreement
|
||||
{
|
||||
private X448PrivateKeyParameters m_privateKey;
|
||||
|
||||
public void Init(ICipherParameters parameters)
|
||||
{
|
||||
m_privateKey = (X448PrivateKeyParameters)parameters;
|
||||
}
|
||||
|
||||
public int AgreementSize
|
||||
{
|
||||
get { return X448PrivateKeyParameters.SecretSize; }
|
||||
}
|
||||
|
||||
public void CalculateAgreement(ICipherParameters publicKey, byte[] buf, int off)
|
||||
{
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
CalculateAgreement(publicKey, buf.AsSpan(off));
|
||||
#else
|
||||
m_privateKey.GenerateSecret((X448PublicKeyParameters)publicKey, buf, off);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public void CalculateAgreement(ICipherParameters publicKey, Span<byte> buf)
|
||||
{
|
||||
m_privateKey.GenerateSecret((X448PublicKeyParameters)publicKey, buf);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5d66ce3e4995fdf43bcdc41991f1eb78
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/jpake.meta
vendored
Normal file
8
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/jpake.meta
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 129fcded50103884aacaaca2ee8f373d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,459 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Digests;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.JPake
|
||||
{
|
||||
/// <summary>
|
||||
/// A participant in a Password Authenticated Key Exchange by Juggling (J-PAKE) exchange.
|
||||
///
|
||||
/// The J-PAKE exchange is defined by Feng Hao and Peter Ryan in the paper
|
||||
/// <a href="http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf">
|
||||
/// "Password Authenticated Key Exchange by Juggling, 2008."</a>
|
||||
///
|
||||
/// The J-PAKE protocol is symmetric.
|
||||
/// There is no notion of a <i>client</i> or <i>server</i>, but rather just two <i>participants</i>.
|
||||
/// An instance of JPakeParticipant represents one participant, and
|
||||
/// is the primary interface for executing the exchange.
|
||||
///
|
||||
/// To execute an exchange, construct a JPakeParticipant on each end,
|
||||
/// and call the following 7 methods
|
||||
/// (once and only once, in the given order, for each participant, sending messages between them as described):
|
||||
///
|
||||
/// CreateRound1PayloadToSend() - and send the payload to the other participant
|
||||
/// ValidateRound1PayloadReceived(JPakeRound1Payload) - use the payload received from the other participant
|
||||
/// CreateRound2PayloadToSend() - and send the payload to the other participant
|
||||
/// ValidateRound2PayloadReceived(JPakeRound2Payload) - use the payload received from the other participant
|
||||
/// CalculateKeyingMaterial()
|
||||
/// CreateRound3PayloadToSend(BigInteger) - and send the payload to the other participant
|
||||
/// ValidateRound3PayloadReceived(JPakeRound3Payload, BigInteger) - use the payload received from the other participant
|
||||
///
|
||||
/// Each side should derive a session key from the keying material returned by CalculateKeyingMaterial().
|
||||
/// The caller is responsible for deriving the session key using a secure key derivation function (KDF).
|
||||
///
|
||||
/// Round 3 is an optional key confirmation process.
|
||||
/// If you do not execute round 3, then there is no assurance that both participants are using the same key.
|
||||
/// (i.e. if the participants used different passwords, then their session keys will differ.)
|
||||
///
|
||||
/// If the round 3 validation succeeds, then the keys are guaranteed to be the same on both sides.
|
||||
///
|
||||
/// The symmetric design can easily support the asymmetric cases when one party initiates the communication.
|
||||
/// e.g. Sometimes the round1 payload and round2 payload may be sent in one pass.
|
||||
/// Also, in some cases, the key confirmation payload can be sent together with the round2 payload.
|
||||
/// These are the trivial techniques to optimize the communication.
|
||||
///
|
||||
/// The key confirmation process is implemented as specified in
|
||||
/// <a href="http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf">NIST SP 800-56A Revision 1</a>,
|
||||
/// Section 8.2 Unilateral Key Confirmation for Key Agreement Schemes.
|
||||
///
|
||||
/// This class is stateful and NOT threadsafe.
|
||||
/// Each instance should only be used for ONE complete J-PAKE exchange
|
||||
/// (i.e. a new JPakeParticipant should be constructed for each new J-PAKE exchange).
|
||||
/// </summary>
|
||||
public class JPakeParticipant
|
||||
{
|
||||
// Possible internal states. Used for state checking.
|
||||
public static readonly int STATE_INITIALIZED = 0;
|
||||
public static readonly int STATE_ROUND_1_CREATED = 10;
|
||||
public static readonly int STATE_ROUND_1_VALIDATED = 20;
|
||||
public static readonly int STATE_ROUND_2_CREATED = 30;
|
||||
public static readonly int STATE_ROUND_2_VALIDATED = 40;
|
||||
public static readonly int STATE_KEY_CALCULATED = 50;
|
||||
public static readonly int STATE_ROUND_3_CREATED = 60;
|
||||
public static readonly int STATE_ROUND_3_VALIDATED = 70;
|
||||
|
||||
// Unique identifier of this participant.
|
||||
// The two participants in the exchange must NOT share the same id.
|
||||
private string participantId;
|
||||
|
||||
// Shared secret. This only contains the secret between construction
|
||||
// and the call to CalculateKeyingMaterial().
|
||||
//
|
||||
// i.e. When CalculateKeyingMaterial() is called, this buffer overwritten with 0's,
|
||||
// and the field is set to null.
|
||||
private char[] password;
|
||||
|
||||
// Digest to use during calculations.
|
||||
private IDigest digest;
|
||||
|
||||
// Source of secure random data.
|
||||
private readonly SecureRandom random;
|
||||
|
||||
private readonly BigInteger p;
|
||||
private readonly BigInteger q;
|
||||
private readonly BigInteger g;
|
||||
|
||||
// The participantId of the other participant in this exchange.
|
||||
private string partnerParticipantId;
|
||||
|
||||
// Alice's x1 or Bob's x3.
|
||||
private BigInteger x1;
|
||||
// Alice's x2 or Bob's x4.
|
||||
private BigInteger x2;
|
||||
// Alice's g^x1 or Bob's g^x3.
|
||||
private BigInteger gx1;
|
||||
// Alice's g^x2 or Bob's g^x4.
|
||||
private BigInteger gx2;
|
||||
// Alice's g^x3 or Bob's g^x1.
|
||||
private BigInteger gx3;
|
||||
// Alice's g^x4 or Bob's g^x2.
|
||||
private BigInteger gx4;
|
||||
// Alice's B or Bob's A.
|
||||
private BigInteger b;
|
||||
|
||||
// The current state.
|
||||
// See the <tt>STATE_*</tt> constants for possible values.
|
||||
private int state;
|
||||
|
||||
/// <summary>
|
||||
/// Convenience constructor for a new JPakeParticipant that uses
|
||||
/// the JPakePrimeOrderGroups#NIST_3072 prime order group,
|
||||
/// a SHA-256 digest, and a default SecureRandom implementation.
|
||||
///
|
||||
/// After construction, the State state will be STATE_INITIALIZED.
|
||||
///
|
||||
/// Throws NullReferenceException if any argument is null. Throws
|
||||
/// ArgumentException if password is empty.
|
||||
/// </summary>
|
||||
/// <param name="participantId">Unique identifier of this participant.
|
||||
/// The two participants in the exchange must NOT share the same id.</param>
|
||||
/// <param name="password">Shared secret.
|
||||
/// A defensive copy of this array is made (and cleared once CalculateKeyingMaterial() is called).
|
||||
/// Caller should clear the input password as soon as possible.</param>
|
||||
public JPakeParticipant(string participantId, char[] password)
|
||||
: this(participantId, password, JPakePrimeOrderGroups.NIST_3072) { }
|
||||
|
||||
/// <summary>
|
||||
/// Convenience constructor for a new JPakeParticipant that uses
|
||||
/// a SHA-256 digest, and a default SecureRandom implementation.
|
||||
///
|
||||
/// After construction, the State state will be STATE_INITIALIZED.
|
||||
///
|
||||
/// Throws NullReferenceException if any argument is null. Throws
|
||||
/// ArgumentException if password is empty.
|
||||
/// </summary>
|
||||
/// <param name="participantId">Unique identifier of this participant.
|
||||
/// The two participants in the exchange must NOT share the same id.</param>
|
||||
/// <param name="password">Shared secret.
|
||||
/// A defensive copy of this array is made (and cleared once CalculateKeyingMaterial() is called).
|
||||
/// Caller should clear the input password as soon as possible.</param>
|
||||
/// <param name="group">Prime order group. See JPakePrimeOrderGroups for standard groups.</param>
|
||||
public JPakeParticipant(string participantId, char[] password, JPakePrimeOrderGroup group)
|
||||
: this(participantId, password, group, new Sha256Digest(), CryptoServicesRegistrar.GetSecureRandom()) { }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for a new JPakeParticipant.
|
||||
///
|
||||
/// After construction, the State state will be STATE_INITIALIZED.
|
||||
///
|
||||
/// Throws NullReferenceException if any argument is null. Throws
|
||||
/// ArgumentException if password is empty.
|
||||
/// </summary>
|
||||
/// <param name="participantId">Unique identifier of this participant.
|
||||
/// The two participants in the exchange must NOT share the same id.</param>
|
||||
/// <param name="password">Shared secret.
|
||||
/// A defensive copy of this array is made (and cleared once CalculateKeyingMaterial() is called).
|
||||
/// Caller should clear the input password as soon as possible.</param>
|
||||
/// <param name="group">Prime order group. See JPakePrimeOrderGroups for standard groups.</param>
|
||||
/// <param name="digest">Digest to use during zero knowledge proofs and key confirmation
|
||||
/// (SHA-256 or stronger preferred).</param>
|
||||
/// <param name="random">Source of secure random data for x1 and x2, and for the zero knowledge proofs.</param>
|
||||
public JPakeParticipant(string participantId, char[] password, JPakePrimeOrderGroup group, IDigest digest,
|
||||
SecureRandom random)
|
||||
{
|
||||
JPakeUtilities.ValidateNotNull(participantId, "participantId");
|
||||
JPakeUtilities.ValidateNotNull(password, "password");
|
||||
JPakeUtilities.ValidateNotNull(group, "p");
|
||||
JPakeUtilities.ValidateNotNull(digest, "digest");
|
||||
JPakeUtilities.ValidateNotNull(random, "random");
|
||||
|
||||
if (password.Length == 0)
|
||||
throw new ArgumentException("Password must not be empty.");
|
||||
|
||||
this.participantId = participantId;
|
||||
|
||||
// Create a defensive copy so as to fully encapsulate the password.
|
||||
//
|
||||
// This array will contain the password for the lifetime of this
|
||||
// participant BEFORE CalculateKeyingMaterial() is called.
|
||||
//
|
||||
// i.e. When CalculateKeyingMaterial() is called, the array will be cleared
|
||||
// in order to remove the password from memory.
|
||||
//
|
||||
// The caller is responsible for clearing the original password array
|
||||
// given as input to this constructor.
|
||||
this.password = new char[password.Length];
|
||||
Array.Copy(password, this.password, password.Length);
|
||||
|
||||
this.p = group.P;
|
||||
this.q = group.Q;
|
||||
this.g = group.G;
|
||||
|
||||
this.digest = digest;
|
||||
this.random = random;
|
||||
|
||||
this.state = STATE_INITIALIZED;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current state of this participant.
|
||||
/// See the <tt>STATE_*</tt> constants for possible values.
|
||||
/// </summary>
|
||||
public virtual int State
|
||||
{
|
||||
get { return state; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates and returns the payload to send to the other participant during round 1.
|
||||
///
|
||||
/// After execution, the State state} will be STATE_ROUND_1_CREATED}.
|
||||
/// </summary>
|
||||
public virtual JPakeRound1Payload CreateRound1PayloadToSend()
|
||||
{
|
||||
if (this.state >= STATE_ROUND_1_CREATED)
|
||||
throw new InvalidOperationException("Round 1 payload already created for " + this.participantId);
|
||||
|
||||
this.x1 = JPakeUtilities.GenerateX1(q, random);
|
||||
this.x2 = JPakeUtilities.GenerateX2(q, random);
|
||||
|
||||
this.gx1 = JPakeUtilities.CalculateGx(p, g, x1);
|
||||
this.gx2 = JPakeUtilities.CalculateGx(p, g, x2);
|
||||
BigInteger[] knowledgeProofForX1 = JPakeUtilities.CalculateZeroKnowledgeProof(p, q, g, gx1, x1, participantId, digest, random);
|
||||
BigInteger[] knowledgeProofForX2 = JPakeUtilities.CalculateZeroKnowledgeProof(p, q, g, gx2, x2, participantId, digest, random);
|
||||
|
||||
this.state = STATE_ROUND_1_CREATED;
|
||||
|
||||
return new JPakeRound1Payload(participantId, gx1, gx2, knowledgeProofForX1, knowledgeProofForX2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the payload received from the other participant during round 1.
|
||||
///
|
||||
/// Must be called prior to CreateRound2PayloadToSend().
|
||||
///
|
||||
/// After execution, the State state will be STATE_ROUND_1_VALIDATED.
|
||||
///
|
||||
/// Throws CryptoException if validation fails. Throws InvalidOperationException
|
||||
/// if called multiple times.
|
||||
/// </summary>
|
||||
public virtual void ValidateRound1PayloadReceived(JPakeRound1Payload round1PayloadReceived)
|
||||
{
|
||||
if (this.state >= STATE_ROUND_1_VALIDATED)
|
||||
throw new InvalidOperationException("Validation already attempted for round 1 payload for " + this.participantId);
|
||||
|
||||
this.partnerParticipantId = round1PayloadReceived.ParticipantId;
|
||||
this.gx3 = round1PayloadReceived.Gx1;
|
||||
this.gx4 = round1PayloadReceived.Gx2;
|
||||
|
||||
BigInteger[] knowledgeProofForX3 = round1PayloadReceived.KnowledgeProofForX1;
|
||||
BigInteger[] knowledgeProofForX4 = round1PayloadReceived.KnowledgeProofForX2;
|
||||
|
||||
JPakeUtilities.ValidateParticipantIdsDiffer(participantId, round1PayloadReceived.ParticipantId);
|
||||
JPakeUtilities.ValidateGx4(gx4);
|
||||
JPakeUtilities.ValidateZeroKnowledgeProof(p, q, g, gx3, knowledgeProofForX3, round1PayloadReceived.ParticipantId, digest);
|
||||
JPakeUtilities.ValidateZeroKnowledgeProof(p, q, g, gx4, knowledgeProofForX4, round1PayloadReceived.ParticipantId, digest);
|
||||
this.state = STATE_ROUND_1_VALIDATED;
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the payload received from the other participant during round 2.
|
||||
/// Note that this DOES NOT detect a non-common password.
|
||||
/// The only indication of a non-common password is through derivation
|
||||
/// of different keys (which can be detected explicitly by executing round 3 and round 4)
|
||||
///
|
||||
/// Must be called prior to CalculateKeyingMaterial().
|
||||
///
|
||||
/// After execution, the State state will be STATE_ROUND_2_VALIDATED.
|
||||
///
|
||||
/// Throws CryptoException if validation fails. Throws
|
||||
/// InvalidOperationException if called prior to ValidateRound1PayloadReceived(JPakeRound1Payload), or multiple times
|
||||
/// </summary>
|
||||
public virtual void ValidateRound2PayloadReceived(JPakeRound2Payload round2PayloadReceived)
|
||||
{
|
||||
if (this.state >= STATE_ROUND_2_VALIDATED)
|
||||
throw new InvalidOperationException("Validation already attempted for round 2 payload for " + this.participantId);
|
||||
if (this.state < STATE_ROUND_1_VALIDATED)
|
||||
throw new InvalidOperationException("Round 1 payload must be validated prior to validation round 2 payload for " + this.participantId);
|
||||
|
||||
BigInteger gB = JPakeUtilities.CalculateGA(p, gx3, gx1, gx2);
|
||||
this.b = round2PayloadReceived.A;
|
||||
BigInteger[] knowledgeProofForX4s = round2PayloadReceived.KnowledgeProofForX2s;
|
||||
|
||||
JPakeUtilities.ValidateParticipantIdsDiffer(participantId, round2PayloadReceived.ParticipantId);
|
||||
JPakeUtilities.ValidateParticipantIdsEqual(this.partnerParticipantId, round2PayloadReceived.ParticipantId);
|
||||
JPakeUtilities.ValidateGa(gB);
|
||||
JPakeUtilities.ValidateZeroKnowledgeProof(p, q, gB, b, knowledgeProofForX4s, round2PayloadReceived.ParticipantId, digest);
|
||||
|
||||
this.state = STATE_ROUND_2_VALIDATED;
|
||||
}
|
||||
|
||||
/// <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 3.
|
||||
///
|
||||
/// See JPakeParticipant for more details on round 3.
|
||||
///
|
||||
/// After execution, the State state} will be STATE_ROUND_3_CREATED.
|
||||
/// Throws InvalidOperationException if called prior to CalculateKeyingMaterial, or multiple
|
||||
/// times.
|
||||
/// </summary>
|
||||
/// <param name="keyingMaterial">The keying material as returned from CalculateKeyingMaterial().</param>
|
||||
public virtual JPakeRound3Payload CreateRound3PayloadToSend(BigInteger keyingMaterial)
|
||||
{
|
||||
if (this.state >= STATE_ROUND_3_CREATED)
|
||||
throw new InvalidOperationException("Round 3 payload already created for " + this.participantId);
|
||||
if (this.state < STATE_KEY_CALCULATED)
|
||||
throw new InvalidOperationException("Keying material must be calculated prior to creating round 3 payload for " + this.participantId);
|
||||
|
||||
BigInteger macTag = JPakeUtilities.CalculateMacTag(
|
||||
this.participantId,
|
||||
this.partnerParticipantId,
|
||||
this.gx1,
|
||||
this.gx2,
|
||||
this.gx3,
|
||||
this.gx4,
|
||||
keyingMaterial,
|
||||
this.digest);
|
||||
|
||||
this.state = STATE_ROUND_3_CREATED;
|
||||
|
||||
return new JPakeRound3Payload(participantId, macTag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the payload received from the other participant during round 3.
|
||||
///
|
||||
/// See JPakeParticipant for more details on round 3.
|
||||
///
|
||||
/// After execution, the State state will be STATE_ROUND_3_VALIDATED.
|
||||
///
|
||||
/// Throws CryptoException if validation fails. Throws InvalidOperationException if called prior to
|
||||
/// CalculateKeyingMaterial or multiple times
|
||||
/// </summary>
|
||||
/// <param name="round3PayloadReceived">The round 3 payload received from the other participant.</param>
|
||||
/// <param name="keyingMaterial">The keying material as returned from CalculateKeyingMaterial().</param>
|
||||
public virtual void ValidateRound3PayloadReceived(JPakeRound3Payload round3PayloadReceived, BigInteger keyingMaterial)
|
||||
{
|
||||
if (this.state >= STATE_ROUND_3_VALIDATED)
|
||||
throw new InvalidOperationException("Validation already attempted for round 3 payload for " + this.participantId);
|
||||
if (this.state < STATE_KEY_CALCULATED)
|
||||
throw new InvalidOperationException("Keying material must be calculated prior to validating round 3 payload for " + this.participantId);
|
||||
|
||||
JPakeUtilities.ValidateParticipantIdsDiffer(participantId, round3PayloadReceived.ParticipantId);
|
||||
JPakeUtilities.ValidateParticipantIdsEqual(this.partnerParticipantId, round3PayloadReceived.ParticipantId);
|
||||
|
||||
JPakeUtilities.ValidateMacTag(
|
||||
this.participantId,
|
||||
this.partnerParticipantId,
|
||||
this.gx1,
|
||||
this.gx2,
|
||||
this.gx3,
|
||||
this.gx4,
|
||||
keyingMaterial,
|
||||
this.digest,
|
||||
round3PayloadReceived.MacTag);
|
||||
|
||||
// Clear the rest of the fields.
|
||||
this.gx1 = null;
|
||||
this.gx2 = null;
|
||||
this.gx3 = null;
|
||||
this.gx4 = null;
|
||||
|
||||
this.state = STATE_ROUND_3_VALIDATED;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a44e1a709319484fbb595c41ceae6f6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,107 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
|
||||
namespace Best.HTTP.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
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f3a2f982f4c3de4dabcd30a73afb055
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,112 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.JPake
|
||||
{
|
||||
/// <summary>
|
||||
/// Standard pre-computed prime order groups for use by J-PAKE.
|
||||
/// (J-PAKE can use pre-computed prime order groups, same as DSA and Diffie-Hellman.)
|
||||
/// <p/>
|
||||
/// This class contains some convenient constants for use as input for
|
||||
/// constructing {@link JPAKEParticipant}s.
|
||||
/// <p/>
|
||||
/// The prime order groups below are taken from Sun's JDK JavaDoc (docs/guide/security/CryptoSpec.html#AppB),
|
||||
/// and from the prime order groups
|
||||
/// <a href="http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/DSA2_All.pdf">published by NIST</a>.
|
||||
/// </summary>
|
||||
public class JPakePrimeOrderGroups
|
||||
{
|
||||
/// <summary>
|
||||
/// From Sun's JDK JavaDoc (docs/guide/security/CryptoSpec.html#AppB)
|
||||
/// 1024-bit p, 160-bit q and 1024-bit g for 80-bit security.
|
||||
/// </summary>
|
||||
public static readonly JPakePrimeOrderGroup SUN_JCE_1024 = new JPakePrimeOrderGroup(
|
||||
// p
|
||||
new BigInteger(
|
||||
"fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80b6512669" +
|
||||
"455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b801d346ff26660b7" +
|
||||
"6b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf83b57e7c6a8a6150f04fb" +
|
||||
"83f6d3c51ec3023554135a169132f675f3ae2b61d72aeff22203199dd14801c7", 16),
|
||||
// q
|
||||
new BigInteger("9760508f15230bccb292b982a2eb840bf0581cf5", 16),
|
||||
// g
|
||||
new BigInteger(
|
||||
"f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b3d078267" +
|
||||
"5159578ebad4594fe67107108180b449167123e84c281613b7cf09328cc8a6e1" +
|
||||
"3c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bfa213562f1fb627a01243b" +
|
||||
"cca4f1bea8519089a883dfe15ae59f06928b665e807b552564014c3bfecf492a", 16),
|
||||
true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// From NIST.
|
||||
/// 2048-bit p, 224-bit q and 2048-bit g for 112-bit security.
|
||||
/// </summary>
|
||||
public static readonly JPakePrimeOrderGroup NIST_2048 = new JPakePrimeOrderGroup(
|
||||
// p
|
||||
new BigInteger(
|
||||
"C196BA05AC29E1F9C3C72D56DFFC6154A033F1477AC88EC37F09BE6C5BB95F51" +
|
||||
"C296DD20D1A28A067CCC4D4316A4BD1DCA55ED1066D438C35AEBAABF57E7DAE4" +
|
||||
"28782A95ECA1C143DB701FD48533A3C18F0FE23557EA7AE619ECACC7E0B51652" +
|
||||
"A8776D02A425567DED36EABD90CA33A1E8D988F0BBB92D02D1D20290113BB562" +
|
||||
"CE1FC856EEB7CDD92D33EEA6F410859B179E7E789A8F75F645FAE2E136D252BF" +
|
||||
"FAFF89528945C1ABE705A38DBC2D364AADE99BE0D0AAD82E5320121496DC65B3" +
|
||||
"930E38047294FF877831A16D5228418DE8AB275D7D75651CEFED65F78AFC3EA7" +
|
||||
"FE4D79B35F62A0402A1117599ADAC7B269A59F353CF450E6982D3B1702D9CA83", 16),
|
||||
// q
|
||||
new BigInteger("90EAF4D1AF0708B1B612FF35E0A2997EB9E9D263C9CE659528945C0D", 16),
|
||||
// g
|
||||
new BigInteger(
|
||||
"A59A749A11242C58C894E9E5A91804E8FA0AC64B56288F8D47D51B1EDC4D6544" +
|
||||
"4FECA0111D78F35FC9FDD4CB1F1B79A3BA9CBEE83A3F811012503C8117F98E50" +
|
||||
"48B089E387AF6949BF8784EBD9EF45876F2E6A5A495BE64B6E770409494B7FEE" +
|
||||
"1DBB1E4B2BC2A53D4F893D418B7159592E4FFFDF6969E91D770DAEBD0B5CB14C" +
|
||||
"00AD68EC7DC1E5745EA55C706C4A1C5C88964E34D09DEB753AD418C1AD0F4FDF" +
|
||||
"D049A955E5D78491C0B7A2F1575A008CCD727AB376DB6E695515B05BD412F5B8" +
|
||||
"C2F4C77EE10DA48ABD53F5DD498927EE7B692BBBCDA2FB23A516C5B4533D7398" +
|
||||
"0B2A3B60E384ED200AE21B40D273651AD6060C13D97FD69AA13C5611A51B9085", 16),
|
||||
true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// From NIST.
|
||||
/// 3072-bit p, 256-bit q and 3072-bit g for 128-bit security.
|
||||
/// </summary>
|
||||
public static readonly JPakePrimeOrderGroup NIST_3072 = new JPakePrimeOrderGroup(
|
||||
// p
|
||||
new BigInteger(
|
||||
"90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD61037E56258A7795A1C" +
|
||||
"7AD46076982CE6BB956936C6AB4DCFE05E6784586940CA544B9B2140E1EB523F" +
|
||||
"009D20A7E7880E4E5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1" +
|
||||
"29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D3485261CD068699B" +
|
||||
"6BA58A1DDBBEF6DB51E8FE34E8A78E542D7BA351C21EA8D8F1D29F5D5D159394" +
|
||||
"87E27F4416B0CA632C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0" +
|
||||
"E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0EE6F29AF7F642773E" +
|
||||
"BE8CD5402415A01451A840476B2FCEB0E388D30D4B376C37FE401C2A2C2F941D" +
|
||||
"AD179C540C1C8CE030D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F" +
|
||||
"B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C560EA878DE87C11E3D" +
|
||||
"597F1FEA742D73EEC7F37BE43949EF1A0D15C3F3E3FC0A8335617055AC91328E" +
|
||||
"C22B50FC15B941D3D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73", 16),
|
||||
// q
|
||||
new BigInteger("CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D", 16),
|
||||
// g
|
||||
new BigInteger(
|
||||
"5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE3B7ACCC54D521E37" +
|
||||
"F84A4BDD5B06B0970CC2D2BBB715F7B82846F9A0C393914C792E6A923E2117AB" +
|
||||
"805276A975AADB5261D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1" +
|
||||
"F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A60126FEB2CF05DB8" +
|
||||
"A7F0F09B3397F3937F2E90B9E5B9C9B6EFEF642BC48351C46FB171B9BFA9EF17" +
|
||||
"A961CE96C7E7A7CC3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C" +
|
||||
"4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B67299E231F8BD90B3" +
|
||||
"9AC3AE3BE0C6B6CACEF8289A2E2873D58E51E029CAFBD55E6841489AB66B5B4B" +
|
||||
"9BA6E2F784660896AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8" +
|
||||
"E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B988567A88126B914D7828" +
|
||||
"E2B63A6D7ED0747EC59E0E0A23CE7D8A74C1D2C2A7AFB6A29799620F00E11C33" +
|
||||
"787F7DED3B30E1A22D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B", 16),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bbd8030d7e46ed341af2da2d455f1725
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,105 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.JPake
|
||||
{
|
||||
/// <summary>
|
||||
/// The payload sent/received during the first round of a J-PAKE exchange.
|
||||
///
|
||||
/// Each JPAKEParticipant creates and sends an instance of this payload to
|
||||
/// the other. The payload to send should be created via
|
||||
/// JPAKEParticipant.CreateRound1PayloadToSend().
|
||||
///
|
||||
/// Each participant must also validate the payload received from the other.
|
||||
/// The received payload should be validated via
|
||||
/// JPAKEParticipant.ValidateRound1PayloadReceived(JPakeRound1Payload).
|
||||
/// </summary>
|
||||
public class JPakeRound1Payload
|
||||
{
|
||||
/// <summary>
|
||||
/// The id of the JPAKEParticipant who created/sent this payload.
|
||||
/// </summary>
|
||||
private readonly string participantId;
|
||||
|
||||
/// <summary>
|
||||
/// The value of g^x1
|
||||
/// </summary>
|
||||
private readonly BigInteger gx1;
|
||||
|
||||
/// <summary>
|
||||
/// The value of g^x2
|
||||
/// </summary>
|
||||
private readonly BigInteger gx2;
|
||||
|
||||
/// <summary>
|
||||
/// The zero knowledge proof for x1.
|
||||
///
|
||||
/// This is a two element array, containing {g^v, r} for x1.
|
||||
/// </summary>
|
||||
private readonly BigInteger[] knowledgeProofForX1;
|
||||
|
||||
/// <summary>
|
||||
/// The zero knowledge proof for x2.
|
||||
///
|
||||
/// This is a two element array, containing {g^v, r} for x2.
|
||||
/// </summary>
|
||||
private readonly BigInteger[] knowledgeProofForX2;
|
||||
|
||||
public JPakeRound1Payload(string participantId, BigInteger gx1, BigInteger gx2, BigInteger[] knowledgeProofForX1, BigInteger[] knowledgeProofForX2)
|
||||
{
|
||||
JPakeUtilities.ValidateNotNull(participantId, "participantId");
|
||||
JPakeUtilities.ValidateNotNull(gx1, "gx1");
|
||||
JPakeUtilities.ValidateNotNull(gx2, "gx2");
|
||||
JPakeUtilities.ValidateNotNull(knowledgeProofForX1, "knowledgeProofForX1");
|
||||
JPakeUtilities.ValidateNotNull(knowledgeProofForX2, "knowledgeProofForX2");
|
||||
|
||||
this.participantId = participantId;
|
||||
this.gx1 = gx1;
|
||||
this.gx2 = gx2;
|
||||
this.knowledgeProofForX1 = new BigInteger[knowledgeProofForX1.Length];
|
||||
Array.Copy(knowledgeProofForX1, this.knowledgeProofForX1, knowledgeProofForX1.Length);
|
||||
this.knowledgeProofForX2 = new BigInteger[knowledgeProofForX2.Length];
|
||||
Array.Copy(knowledgeProofForX2, this.knowledgeProofForX2, knowledgeProofForX2.Length);
|
||||
}
|
||||
|
||||
public virtual string ParticipantId
|
||||
{
|
||||
get { return participantId; }
|
||||
}
|
||||
|
||||
public virtual BigInteger Gx1
|
||||
{
|
||||
get { return gx1; }
|
||||
}
|
||||
|
||||
public virtual BigInteger Gx2
|
||||
{
|
||||
get { return gx2; }
|
||||
}
|
||||
|
||||
public virtual BigInteger[] KnowledgeProofForX1
|
||||
{
|
||||
get
|
||||
{
|
||||
BigInteger[] kp = new BigInteger[knowledgeProofForX1.Length];
|
||||
Array.Copy(knowledgeProofForX1, kp, knowledgeProofForX1.Length);
|
||||
return kp;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual BigInteger[] KnowledgeProofForX2
|
||||
{
|
||||
get
|
||||
{
|
||||
BigInteger[] kp = new BigInteger[knowledgeProofForX2.Length];
|
||||
Array.Copy(knowledgeProofForX2, kp, knowledgeProofForX2.Length);
|
||||
return kp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa863481cc9acaa46adf027ef83a163c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,76 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.JPake
|
||||
{
|
||||
/// <summary>
|
||||
/// The payload sent/received during the second round of a J-PAKE exchange.
|
||||
///
|
||||
/// Each JPAKEParticipant creates and sends an instance
|
||||
/// of this payload to the other JPAKEParticipant.
|
||||
/// The payload to send should be created via
|
||||
/// JPAKEParticipant#createRound2PayloadToSend()
|
||||
///
|
||||
/// Each JPAKEParticipant must also validate the payload
|
||||
/// received from the other JPAKEParticipant.
|
||||
/// The received payload should be validated via
|
||||
/// JPAKEParticipant#validateRound2PayloadReceived(JPakeRound2Payload)
|
||||
/// </summary>
|
||||
public class JPakeRound2Payload
|
||||
{
|
||||
/// <summary>
|
||||
/// The id of the JPAKEParticipant who created/sent this payload.
|
||||
/// </summary>
|
||||
private readonly string participantId;
|
||||
|
||||
/// <summary>
|
||||
/// The value of A, as computed during round 2.
|
||||
/// </summary>
|
||||
private readonly BigInteger a;
|
||||
|
||||
/// <summary>
|
||||
/// The zero knowledge proof for x2 * s.
|
||||
///
|
||||
/// This is a two element array, containing {g^v, r} for x2 * s.
|
||||
/// </summary>
|
||||
private readonly BigInteger[] knowledgeProofForX2s;
|
||||
|
||||
public JPakeRound2Payload(string participantId, BigInteger a, BigInteger[] knowledgeProofForX2s)
|
||||
{
|
||||
JPakeUtilities.ValidateNotNull(participantId, "participantId");
|
||||
JPakeUtilities.ValidateNotNull(a, "a");
|
||||
JPakeUtilities.ValidateNotNull(knowledgeProofForX2s, "knowledgeProofForX2s");
|
||||
|
||||
this.participantId = participantId;
|
||||
this.a = a;
|
||||
this.knowledgeProofForX2s = new BigInteger[knowledgeProofForX2s.Length];
|
||||
knowledgeProofForX2s.CopyTo(this.knowledgeProofForX2s, 0);
|
||||
}
|
||||
|
||||
public virtual string ParticipantId
|
||||
{
|
||||
get { return participantId; }
|
||||
}
|
||||
|
||||
public virtual BigInteger A
|
||||
{
|
||||
get { return a; }
|
||||
}
|
||||
|
||||
public virtual BigInteger[] KnowledgeProofForX2s
|
||||
{
|
||||
get
|
||||
{
|
||||
BigInteger[] kp = new BigInteger[knowledgeProofForX2s.Length];
|
||||
Array.Copy(knowledgeProofForX2s, kp, knowledgeProofForX2s.Length);
|
||||
return kp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d8402c23ea397d0458cccdd653d7dfa0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,55 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.JPake
|
||||
{
|
||||
/// <summary>
|
||||
/// The payload sent/received during the optional third round of a J-PAKE exchange,
|
||||
/// which is for explicit key confirmation.
|
||||
///
|
||||
/// Each JPAKEParticipant creates and sends an instance
|
||||
/// of this payload to the other JPAKEParticipant.
|
||||
/// The payload to send should be created via
|
||||
/// JPAKEParticipant#createRound3PayloadToSend(BigInteger)
|
||||
///
|
||||
/// Eeach JPAKEParticipant must also validate the payload
|
||||
/// received from the other JPAKEParticipant.
|
||||
/// The received payload should be validated via
|
||||
/// JPAKEParticipant#validateRound3PayloadReceived(JPakeRound3Payload, BigInteger)
|
||||
/// </summary>
|
||||
public class JPakeRound3Payload
|
||||
{
|
||||
/// <summary>
|
||||
/// The id of the {@link JPAKEParticipant} who created/sent this payload.
|
||||
/// </summary>
|
||||
private readonly string participantId;
|
||||
|
||||
/// <summary>
|
||||
/// The value of MacTag, as computed by round 3.
|
||||
///
|
||||
/// See JPAKEUtil#calculateMacTag(string, string, BigInteger, BigInteger, BigInteger, BigInteger, BigInteger, org.bouncycastle.crypto.Digest)
|
||||
/// </summary>
|
||||
private readonly BigInteger macTag;
|
||||
|
||||
public JPakeRound3Payload(string participantId, BigInteger magTag)
|
||||
{
|
||||
this.participantId = participantId;
|
||||
this.macTag = magTag;
|
||||
}
|
||||
|
||||
public virtual string ParticipantId
|
||||
{
|
||||
get { return participantId; }
|
||||
}
|
||||
|
||||
public virtual BigInteger MacTag
|
||||
{
|
||||
get { return macTag; }
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f379951a5b959e540bd121ac5d44fcef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,394 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Macs;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.JPake
|
||||
{
|
||||
/// <summary>
|
||||
/// Primitives needed for a J-PAKE exchange.
|
||||
///
|
||||
/// The recommended way to perform a J-PAKE exchange is by using
|
||||
/// two JPAKEParticipants. Internally, those participants
|
||||
/// call these primitive operations in JPakeUtilities.
|
||||
///
|
||||
/// The primitives, however, can be used without a JPAKEParticipant if needed.
|
||||
/// </summary>
|
||||
public abstract class JPakeUtilities
|
||||
{
|
||||
public static readonly BigInteger Zero = BigInteger.Zero;
|
||||
public static readonly BigInteger One = BigInteger.One;
|
||||
|
||||
/// <summary>
|
||||
/// Return a value that can be used as x1 or x3 during round 1.
|
||||
/// The returned value is a random value in the range [0, q-1].
|
||||
/// </summary>
|
||||
public static BigInteger GenerateX1(BigInteger q, SecureRandom random)
|
||||
{
|
||||
BigInteger min = Zero;
|
||||
BigInteger max = q.Subtract(One);
|
||||
return BigIntegers.CreateRandomInRange(min, max, random);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a value that can be used as x2 or x4 during round 1.
|
||||
/// The returned value is a random value in the range [1, q-1].
|
||||
/// </summary>
|
||||
public static BigInteger GenerateX2(BigInteger q, SecureRandom random)
|
||||
{
|
||||
BigInteger min = One;
|
||||
BigInteger max = q.Subtract(One);
|
||||
return BigIntegers.CreateRandomInRange(min, max, random);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given password to a BigInteger
|
||||
/// for use in arithmetic calculations.
|
||||
/// </summary>
|
||||
public static BigInteger CalculateS(char[] password)
|
||||
{
|
||||
return new BigInteger(Encoding.UTF8.GetBytes(password));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate g^x mod p as done in round 1.
|
||||
/// </summary>
|
||||
public static BigInteger CalculateGx(BigInteger p, BigInteger g, BigInteger x)
|
||||
{
|
||||
return g.ModPow(x, p);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate ga as done in round 2.
|
||||
/// </summary>
|
||||
public static BigInteger CalculateGA(BigInteger p, BigInteger gx1, BigInteger gx3, BigInteger gx4)
|
||||
{
|
||||
// ga = g^(x1+x3+x4) = g^x1 * g^x3 * g^x4
|
||||
return gx1.Multiply(gx3).Multiply(gx4).Mod(p);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate x2 * s as done in round 2.
|
||||
/// </summary>
|
||||
public static BigInteger CalculateX2s(BigInteger q, BigInteger x2, BigInteger s)
|
||||
{
|
||||
return x2.Multiply(s).Mod(q);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate A as done in round 2.
|
||||
/// </summary>
|
||||
public static BigInteger CalculateA(BigInteger p, BigInteger q, BigInteger gA, BigInteger x2s)
|
||||
{
|
||||
// A = ga^(x*s)
|
||||
return gA.ModPow(x2s, p);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate a zero knowledge proof of x using Schnorr's signature.
|
||||
/// The returned array has two elements {g^v, r = v-x*h} for x.
|
||||
/// </summary>
|
||||
public static BigInteger[] CalculateZeroKnowledgeProof(BigInteger p, BigInteger q, BigInteger g,
|
||||
BigInteger gx, BigInteger x, string participantId, IDigest digest, SecureRandom random)
|
||||
{
|
||||
/* Generate a random v, and compute g^v */
|
||||
BigInteger vMin = Zero;
|
||||
BigInteger vMax = q.Subtract(One);
|
||||
BigInteger v = BigIntegers.CreateRandomInRange(vMin, vMax, random);
|
||||
|
||||
BigInteger gv = g.ModPow(v, p);
|
||||
BigInteger h = CalculateHashForZeroKnowledgeProof(g, gv, gx, participantId, digest); // h
|
||||
|
||||
return new BigInteger[]
|
||||
{
|
||||
gv,
|
||||
v.Subtract(x.Multiply(h)).Mod(q) // r = v-x*h
|
||||
};
|
||||
}
|
||||
|
||||
private static BigInteger CalculateHashForZeroKnowledgeProof(BigInteger g, BigInteger gr, BigInteger gx,
|
||||
string participantId, IDigest digest)
|
||||
{
|
||||
digest.Reset();
|
||||
|
||||
UpdateDigestIncludingSize(digest, g);
|
||||
|
||||
UpdateDigestIncludingSize(digest, gr);
|
||||
|
||||
UpdateDigestIncludingSize(digest, gx);
|
||||
|
||||
UpdateDigestIncludingSize(digest, participantId);
|
||||
|
||||
byte[] output = DigestUtilities.DoFinal(digest);
|
||||
|
||||
return new BigInteger(output);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that g^x4 is not 1.
|
||||
/// throws CryptoException if g^x4 is 1
|
||||
/// </summary>
|
||||
public static void ValidateGx4(BigInteger gx4)
|
||||
{
|
||||
if (gx4.Equals(One))
|
||||
throw new CryptoException("g^x validation failed. g^x should not be 1.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that ga is not 1.
|
||||
///
|
||||
/// As described by Feng Hao...
|
||||
/// Alice could simply check ga != 1 to ensure it is a generator.
|
||||
/// In fact, as we will explain in Section 3, (x1 + x3 + x4 ) is random over Zq even in the face of active attacks.
|
||||
/// Hence, the probability for ga = 1 is extremely small - on the order of 2^160 for 160-bit q.
|
||||
///
|
||||
/// throws CryptoException if ga is 1
|
||||
/// </summary>
|
||||
public static void ValidateGa(BigInteger ga)
|
||||
{
|
||||
if (ga.Equals(One))
|
||||
throw new CryptoException("ga is equal to 1. It should not be. The chances of this happening are on the order of 2^160 for a 160-bit q. Try again.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the zero knowledge proof (generated by
|
||||
/// calculateZeroKnowledgeProof(BigInteger, BigInteger, BigInteger, BigInteger, BigInteger, string, Digest, SecureRandom)
|
||||
/// is correct.
|
||||
///
|
||||
/// throws CryptoException if the zero knowledge proof is not correct
|
||||
/// </summary>
|
||||
public static void ValidateZeroKnowledgeProof(BigInteger p, BigInteger q, BigInteger g,
|
||||
BigInteger gx, BigInteger[] zeroKnowledgeProof, string participantId, IDigest digest)
|
||||
{
|
||||
/* sig={g^v,r} */
|
||||
BigInteger gv = zeroKnowledgeProof[0];
|
||||
BigInteger r = zeroKnowledgeProof[1];
|
||||
|
||||
BigInteger h = CalculateHashForZeroKnowledgeProof(g, gv, gx, participantId, digest);
|
||||
if (!(gx.CompareTo(Zero) == 1 && // g^x > 0
|
||||
gx.CompareTo(p) == -1 && // g^x < p
|
||||
gx.ModPow(q, p).CompareTo(One) == 0 && // g^x^q mod q = 1
|
||||
/*
|
||||
* Below, I took a straightforward way to compute g^r * g^x^h,
|
||||
* which needs 2 exp. Using a simultaneous computation technique
|
||||
* would only need 1 exp.
|
||||
*/
|
||||
g.ModPow(r, p).Multiply(gx.ModPow(h, p)).Mod(p).CompareTo(gv) == 0)) // g^v=g^r * g^x^h
|
||||
{
|
||||
throw new CryptoException("Zero-knowledge proof validation failed");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the keying material, which can be done after round 2 has completed.
|
||||
/// 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).
|
||||
///
|
||||
/// KeyingMaterial = (B/g^{x2*x4*s})^x2
|
||||
/// </summary>
|
||||
public static BigInteger CalculateKeyingMaterial(BigInteger p, BigInteger q,
|
||||
BigInteger gx4, BigInteger x2, BigInteger s, BigInteger B)
|
||||
{
|
||||
return gx4.ModPow(x2.Multiply(s).Negate().Mod(q), p).Multiply(B).ModPow(x2, p);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that the given participant ids are not equal.
|
||||
/// (For the J-PAKE exchange, each participant must use a unique id.)
|
||||
///
|
||||
/// Throws CryptoException if the participantId strings are equal.
|
||||
/// </summary>
|
||||
public static void ValidateParticipantIdsDiffer(string participantId1, string participantId2)
|
||||
{
|
||||
if (participantId1.Equals(participantId2))
|
||||
{
|
||||
throw new CryptoException(
|
||||
"Both participants are using the same participantId ("
|
||||
+ participantId1
|
||||
+ "). This is not allowed. "
|
||||
+ "Each participant must use a unique participantId.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that the given participant ids are equal.
|
||||
/// This is used to ensure that the payloads received from
|
||||
/// each round all come from the same participant.
|
||||
/// </summary>
|
||||
public static void ValidateParticipantIdsEqual(string expectedParticipantId, string actualParticipantId)
|
||||
{
|
||||
if (!expectedParticipantId.Equals(actualParticipantId))
|
||||
{
|
||||
throw new CryptoException(
|
||||
"Received payload from incorrect partner ("
|
||||
+ actualParticipantId
|
||||
+ "). Expected to receive payload from "
|
||||
+ expectedParticipantId
|
||||
+ ".");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that the given object is not null.
|
||||
/// throws NullReferenceException if the object is null.
|
||||
/// </summary>
|
||||
/// <param name="obj">object in question</param>
|
||||
/// <param name="description">name of the object (to be used in exception message)</param>
|
||||
public static void ValidateNotNull(object obj, string description)
|
||||
{
|
||||
if (obj == null)
|
||||
throw new ArgumentNullException(description);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the MacTag (to be used for key confirmation), as defined by
|
||||
/// <a href="http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf">NIST SP 800-56A Revision 1</a>,
|
||||
/// Section 8.2 Unilateral Key Confirmation for Key Agreement Schemes.
|
||||
///
|
||||
/// MacTag = HMAC(MacKey, MacLen, MacData)
|
||||
/// MacKey = H(K || "JPAKE_KC")
|
||||
/// MacData = "KC_1_U" || participantId || partnerParticipantId || gx1 || gx2 || gx3 || gx4
|
||||
///
|
||||
/// Note that both participants use "KC_1_U" because the sender of the round 3 message
|
||||
/// is always the initiator for key confirmation.
|
||||
///
|
||||
/// HMAC = {@link HMac} used with the given {@link Digest}
|
||||
/// H = The given {@link Digest}
|
||||
/// MacLen = length of MacTag
|
||||
/// </summary>
|
||||
public static BigInteger CalculateMacTag(string participantId, string partnerParticipantId,
|
||||
BigInteger gx1, BigInteger gx2, BigInteger gx3, BigInteger gx4, BigInteger keyingMaterial, IDigest digest)
|
||||
{
|
||||
byte[] macKey = CalculateMacKey(keyingMaterial, digest);
|
||||
|
||||
HMac mac = new HMac(digest);
|
||||
mac.Init(new KeyParameter(macKey));
|
||||
Arrays.Fill(macKey, (byte)0);
|
||||
|
||||
/*
|
||||
* MacData = "KC_1_U" || participantId_Alice || participantId_Bob || gx1 || gx2 || gx3 || gx4.
|
||||
*/
|
||||
UpdateMac(mac, "KC_1_U");
|
||||
UpdateMac(mac, participantId);
|
||||
UpdateMac(mac, partnerParticipantId);
|
||||
UpdateMac(mac, gx1);
|
||||
UpdateMac(mac, gx2);
|
||||
UpdateMac(mac, gx3);
|
||||
UpdateMac(mac, gx4);
|
||||
|
||||
byte[] macOutput = MacUtilities.DoFinal(mac);
|
||||
|
||||
return new BigInteger(macOutput);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the MacKey (i.e. the key to use when calculating the MagTag for key confirmation).
|
||||
///
|
||||
/// MacKey = H(K || "JPAKE_KC")
|
||||
/// </summary>
|
||||
private static byte[] CalculateMacKey(BigInteger keyingMaterial, IDigest digest)
|
||||
{
|
||||
digest.Reset();
|
||||
|
||||
UpdateDigest(digest, keyingMaterial);
|
||||
/*
|
||||
* This constant is used to ensure that the macKey is NOT the same as the derived key.
|
||||
*/
|
||||
UpdateDigest(digest, "JPAKE_KC");
|
||||
|
||||
return DigestUtilities.DoFinal(digest);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the MacTag received from the partner participant.
|
||||
///
|
||||
/// throws CryptoException if the participantId strings are equal.
|
||||
/// </summary>
|
||||
public static void ValidateMacTag(string participantId, string partnerParticipantId,
|
||||
BigInteger gx1, BigInteger gx2, BigInteger gx3, BigInteger gx4,
|
||||
BigInteger keyingMaterial, IDigest digest, BigInteger partnerMacTag)
|
||||
{
|
||||
/*
|
||||
* Calculate the expected MacTag using the parameters as the partner
|
||||
* would have used when the partner called calculateMacTag.
|
||||
*
|
||||
* i.e. basically all the parameters are reversed.
|
||||
* participantId <-> partnerParticipantId
|
||||
* x1 <-> x3
|
||||
* x2 <-> x4
|
||||
*/
|
||||
BigInteger expectedMacTag = CalculateMacTag(partnerParticipantId, participantId, gx3, gx4, gx1, gx2, keyingMaterial, digest);
|
||||
|
||||
if (!expectedMacTag.Equals(partnerMacTag))
|
||||
{
|
||||
throw new CryptoException(
|
||||
"Partner MacTag validation failed. "
|
||||
+ "Therefore, the password, MAC, or digest algorithm of each participant does not match.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateDigest(IDigest digest, BigInteger bigInteger)
|
||||
{
|
||||
UpdateDigest(digest, BigIntegers.AsUnsignedByteArray(bigInteger));
|
||||
}
|
||||
|
||||
private static void UpdateDigest(IDigest digest, string str)
|
||||
{
|
||||
UpdateDigest(digest, Encoding.UTF8.GetBytes(str));
|
||||
}
|
||||
|
||||
private static void UpdateDigest(IDigest digest, byte[] bytes)
|
||||
{
|
||||
digest.BlockUpdate(bytes, 0, bytes.Length);
|
||||
Arrays.Fill(bytes, (byte)0);
|
||||
}
|
||||
|
||||
private static void UpdateDigestIncludingSize(IDigest digest, BigInteger bigInteger)
|
||||
{
|
||||
UpdateDigestIncludingSize(digest, BigIntegers.AsUnsignedByteArray(bigInteger));
|
||||
}
|
||||
|
||||
private static void UpdateDigestIncludingSize(IDigest digest, string str)
|
||||
{
|
||||
UpdateDigestIncludingSize(digest, Encoding.UTF8.GetBytes(str));
|
||||
}
|
||||
|
||||
private static void UpdateDigestIncludingSize(IDigest digest, byte[] bytes)
|
||||
{
|
||||
digest.BlockUpdate(IntToByteArray(bytes.Length), 0, 4);
|
||||
digest.BlockUpdate(bytes, 0, bytes.Length);
|
||||
Arrays.Fill(bytes, (byte)0);
|
||||
}
|
||||
|
||||
private static void UpdateMac(IMac mac, BigInteger bigInteger)
|
||||
{
|
||||
UpdateMac(mac, BigIntegers.AsUnsignedByteArray(bigInteger));
|
||||
}
|
||||
|
||||
private static void UpdateMac(IMac mac, string str)
|
||||
{
|
||||
UpdateMac(mac, Encoding.UTF8.GetBytes(str));
|
||||
}
|
||||
|
||||
private static void UpdateMac(IMac mac, byte[] bytes)
|
||||
{
|
||||
mac.BlockUpdate(bytes, 0, bytes.Length);
|
||||
Arrays.Fill(bytes, (byte)0);
|
||||
}
|
||||
|
||||
private static byte[] IntToByteArray(int value)
|
||||
{
|
||||
return Pack.UInt32_To_BE((uint)value);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 044dab773d7b78b4a890e0ed2e9f9db8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/kdf.meta
vendored
Normal file
8
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/kdf.meta
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c49be985df51f014b95e1156902b4d8d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,118 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.Kdf
|
||||
{
|
||||
/// <summary>Generator for Concatenation Key Derivation Function defined in NIST SP 800-56A, Sect 5.8.1</summary>
|
||||
public sealed class ConcatenationKdfGenerator
|
||||
: IDerivationFunction
|
||||
{
|
||||
private readonly IDigest m_digest;
|
||||
private readonly int m_hLen;
|
||||
|
||||
private byte[] m_buffer;
|
||||
|
||||
/// <param name="digest">the digest to be used as the source of generated bytes</param>
|
||||
public ConcatenationKdfGenerator(IDigest digest)
|
||||
{
|
||||
m_digest = digest;
|
||||
m_hLen = digest.GetDigestSize();
|
||||
}
|
||||
|
||||
public void Init(IDerivationParameters param)
|
||||
{
|
||||
if (!(param is KdfParameters kdfParameters))
|
||||
throw new ArgumentException("KDF parameters required for ConcatenationKdfGenerator");
|
||||
|
||||
byte[] sharedSecret = kdfParameters.GetSharedSecret();
|
||||
byte[] otherInfo = kdfParameters.GetIV();
|
||||
|
||||
m_buffer = new byte[4 + sharedSecret.Length + otherInfo.Length + m_hLen];
|
||||
sharedSecret.CopyTo(m_buffer, 4);
|
||||
otherInfo.CopyTo(m_buffer, 4 + sharedSecret.Length);
|
||||
}
|
||||
|
||||
/// <summary>the underlying digest.</summary>
|
||||
public IDigest Digest => m_digest;
|
||||
|
||||
/// <summary>Fill <c>len</c> bytes of the output buffer with bytes generated from the derivation function.
|
||||
/// </summary>
|
||||
public int GenerateBytes(byte[] output, int outOff, int length)
|
||||
{
|
||||
Check.OutputLength(output, outOff, length, "output buffer too small");
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
return GenerateBytes(output.AsSpan(outOff, length));
|
||||
#else
|
||||
int hashPos = m_buffer.Length - m_hLen;
|
||||
uint counter = 1;
|
||||
|
||||
m_digest.Reset();
|
||||
|
||||
int end = outOff + length;
|
||||
int limit = end - m_hLen;
|
||||
|
||||
while (outOff <= limit)
|
||||
{
|
||||
Pack.UInt32_To_BE(counter++, m_buffer, 0);
|
||||
|
||||
m_digest.BlockUpdate(m_buffer, 0, hashPos);
|
||||
m_digest.DoFinal(output, outOff);
|
||||
|
||||
outOff += m_hLen;
|
||||
}
|
||||
|
||||
if (outOff < end)
|
||||
{
|
||||
Pack.UInt32_To_BE(counter, m_buffer, 0);
|
||||
|
||||
m_digest.BlockUpdate(m_buffer, 0, hashPos);
|
||||
m_digest.DoFinal(m_buffer, hashPos);
|
||||
|
||||
Array.Copy(m_buffer, hashPos, output, outOff, end - outOff);
|
||||
}
|
||||
|
||||
return length;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public int GenerateBytes(Span<byte> output)
|
||||
{
|
||||
int hashPos = m_buffer.Length - m_hLen;
|
||||
uint counter = 1;
|
||||
|
||||
m_digest.Reset();
|
||||
|
||||
int pos = 0, length = output.Length, limit = length - m_hLen;
|
||||
|
||||
while (pos <= limit)
|
||||
{
|
||||
Pack.UInt32_To_BE(counter++, m_buffer.AsSpan());
|
||||
|
||||
m_digest.BlockUpdate(m_buffer.AsSpan(0, hashPos));
|
||||
m_digest.DoFinal(output[pos..]);
|
||||
|
||||
pos += m_hLen;
|
||||
}
|
||||
|
||||
if (pos < length)
|
||||
{
|
||||
Pack.UInt32_To_BE(counter, m_buffer.AsSpan());
|
||||
|
||||
m_digest.BlockUpdate(m_buffer.AsSpan(0, hashPos));
|
||||
m_digest.DoFinal(m_buffer.AsSpan(hashPos));
|
||||
m_buffer.AsSpan(hashPos, length - pos).CopyTo(output[pos..]);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8557a9f5b3111342a056dc6d2f6a673
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,61 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.Kdf
|
||||
{
|
||||
public class DHKdfParameters
|
||||
: IDerivationParameters
|
||||
{
|
||||
private readonly DerObjectIdentifier algorithm;
|
||||
private readonly int keySize;
|
||||
private readonly byte[] z;
|
||||
private readonly byte[] extraInfo;
|
||||
|
||||
public DHKdfParameters(
|
||||
DerObjectIdentifier algorithm,
|
||||
int keySize,
|
||||
byte[] z)
|
||||
: this(algorithm, keySize, z, null)
|
||||
{
|
||||
}
|
||||
|
||||
public DHKdfParameters(
|
||||
DerObjectIdentifier algorithm,
|
||||
int keySize,
|
||||
byte[] z,
|
||||
byte[] extraInfo)
|
||||
{
|
||||
this.algorithm = algorithm;
|
||||
this.keySize = keySize;
|
||||
this.z = z; // TODO Clone?
|
||||
this.extraInfo = extraInfo;
|
||||
}
|
||||
|
||||
public DerObjectIdentifier Algorithm
|
||||
{
|
||||
get { return algorithm; }
|
||||
}
|
||||
|
||||
public int KeySize
|
||||
{
|
||||
get { return keySize; }
|
||||
}
|
||||
|
||||
public byte[] GetZ()
|
||||
{
|
||||
// TODO Clone?
|
||||
return z;
|
||||
}
|
||||
|
||||
public byte[] GetExtraInfo()
|
||||
{
|
||||
// TODO Clone?
|
||||
return extraInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63ca39658cd060b499a676c8c3fbfd2a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
174
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/kdf/DHKekGenerator.cs
vendored
Normal file
174
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/kdf/DHKekGenerator.cs
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.IO;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.Kdf
|
||||
{
|
||||
/**
|
||||
* RFC 2631 Diffie-hellman KEK derivation function.
|
||||
*/
|
||||
public sealed class DHKekGenerator
|
||||
: IDerivationFunction
|
||||
{
|
||||
private readonly IDigest m_digest;
|
||||
|
||||
private DerObjectIdentifier algorithm;
|
||||
private int keySize;
|
||||
private byte[] z;
|
||||
private byte[] partyAInfo;
|
||||
|
||||
public DHKekGenerator(IDigest digest)
|
||||
{
|
||||
m_digest = digest;
|
||||
}
|
||||
|
||||
public void Init(IDerivationParameters param)
|
||||
{
|
||||
DHKdfParameters parameters = (DHKdfParameters)param;
|
||||
|
||||
this.algorithm = parameters.Algorithm;
|
||||
this.keySize = parameters.KeySize;
|
||||
this.z = parameters.GetZ(); // TODO Clone?
|
||||
this.partyAInfo = parameters.GetExtraInfo(); // TODO Clone?
|
||||
}
|
||||
|
||||
public IDigest Digest => m_digest;
|
||||
|
||||
public int GenerateBytes(byte[] outBytes, int outOff, int length)
|
||||
{
|
||||
Check.OutputLength(outBytes, outOff, length, "output buffer too small");
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
return GenerateBytes(outBytes.AsSpan(outOff, length));
|
||||
#else
|
||||
long oBytes = length;
|
||||
int digestSize = m_digest.GetDigestSize();
|
||||
|
||||
//
|
||||
// this is at odds with the standard implementation, the
|
||||
// maximum value should be hBits * (2^32 - 1) where hBits
|
||||
// is the digest output size in bits. We can't have an
|
||||
// array with a long index at the moment...
|
||||
//
|
||||
if (oBytes > ((2L << 32) - 1))
|
||||
throw new ArgumentException("Output length too large");
|
||||
|
||||
int cThreshold = (int)((oBytes + digestSize - 1) / digestSize);
|
||||
|
||||
byte[] dig = new byte[digestSize];
|
||||
|
||||
uint counter = 1;
|
||||
|
||||
for (int i = 0; i < cThreshold; i++)
|
||||
{
|
||||
// KeySpecificInfo
|
||||
DerSequence keyInfo = new DerSequence(algorithm, new DerOctetString(Pack.UInt32_To_BE(counter)));
|
||||
|
||||
// OtherInfo
|
||||
Asn1EncodableVector v1 = new Asn1EncodableVector(keyInfo);
|
||||
|
||||
if (partyAInfo != null)
|
||||
{
|
||||
v1.Add(new DerTaggedObject(true, 0, new DerOctetString(partyAInfo)));
|
||||
}
|
||||
|
||||
v1.Add(new DerTaggedObject(true, 2, new DerOctetString(Pack.UInt32_To_BE((uint)keySize))));
|
||||
|
||||
byte[] other = new DerSequence(v1).GetDerEncoded();
|
||||
|
||||
m_digest.BlockUpdate(z, 0, z.Length);
|
||||
m_digest.BlockUpdate(other, 0, other.Length);
|
||||
m_digest.DoFinal(dig, 0);
|
||||
|
||||
if (length > digestSize)
|
||||
{
|
||||
Array.Copy(dig, 0, outBytes, outOff, digestSize);
|
||||
outOff += digestSize;
|
||||
length -= digestSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
Array.Copy(dig, 0, outBytes, outOff, length);
|
||||
}
|
||||
|
||||
counter++;
|
||||
}
|
||||
|
||||
m_digest.Reset();
|
||||
|
||||
return (int)oBytes;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public int GenerateBytes(Span<byte> output)
|
||||
{
|
||||
long oBytes = output.Length;
|
||||
int digestSize = m_digest.GetDigestSize();
|
||||
|
||||
//
|
||||
// this is at odds with the standard implementation, the
|
||||
// maximum value should be hBits * (2^32 - 1) where hBits
|
||||
// is the digest output size in bits. We can't have an
|
||||
// array with a long index at the moment...
|
||||
//
|
||||
if (oBytes > ((2L << 32) - 1))
|
||||
throw new ArgumentException("Output length too large");
|
||||
|
||||
int cThreshold = (int)((oBytes + digestSize - 1) / digestSize);
|
||||
|
||||
Span<byte> dig = digestSize <= 128
|
||||
? stackalloc byte[digestSize]
|
||||
: new byte[digestSize];
|
||||
|
||||
uint counter = 1;
|
||||
|
||||
for (int i = 0; i < cThreshold; i++)
|
||||
{
|
||||
// KeySpecificInfo
|
||||
DerSequence keyInfo = new DerSequence(algorithm, new DerOctetString(Pack.UInt32_To_BE(counter)));
|
||||
|
||||
// OtherInfo
|
||||
Asn1EncodableVector v1 = new Asn1EncodableVector(keyInfo);
|
||||
|
||||
if (partyAInfo != null)
|
||||
{
|
||||
v1.Add(new DerTaggedObject(true, 0, new DerOctetString(partyAInfo)));
|
||||
}
|
||||
|
||||
v1.Add(new DerTaggedObject(true, 2, new DerOctetString(Pack.UInt32_To_BE((uint)keySize))));
|
||||
|
||||
byte[] other = new DerSequence(v1).GetDerEncoded();
|
||||
|
||||
m_digest.BlockUpdate(z);
|
||||
m_digest.BlockUpdate(other);
|
||||
m_digest.DoFinal(dig);
|
||||
|
||||
int remaining = output.Length;
|
||||
if (remaining > digestSize)
|
||||
{
|
||||
dig.CopyTo(output);
|
||||
output = output[digestSize..];
|
||||
}
|
||||
else
|
||||
{
|
||||
dig[..remaining].CopyTo(output);
|
||||
}
|
||||
|
||||
counter++;
|
||||
}
|
||||
|
||||
m_digest.Reset();
|
||||
|
||||
return (int)oBytes;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60c48eaaa5f539640a6ffb1923dc4cb7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,77 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Generators;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.Kdf
|
||||
{
|
||||
/**
|
||||
* X9.63 based key derivation function for ECDH CMS.
|
||||
*/
|
||||
public sealed class ECDHKekGenerator
|
||||
: IDerivationFunction
|
||||
{
|
||||
private readonly IDerivationFunction m_kdf;
|
||||
|
||||
private DerObjectIdentifier algorithm;
|
||||
private int keySize;
|
||||
private byte[] z;
|
||||
|
||||
public ECDHKekGenerator(IDigest digest)
|
||||
{
|
||||
m_kdf = new Kdf2BytesGenerator(digest);
|
||||
}
|
||||
|
||||
public void Init(IDerivationParameters param)
|
||||
{
|
||||
DHKdfParameters parameters = (DHKdfParameters)param;
|
||||
|
||||
this.algorithm = parameters.Algorithm;
|
||||
this.keySize = parameters.KeySize;
|
||||
this.z = parameters.GetZ(); // TODO Clone?
|
||||
}
|
||||
|
||||
public IDigest Digest => m_kdf.Digest;
|
||||
|
||||
public int GenerateBytes(byte[] outBytes, int outOff, int length)
|
||||
{
|
||||
Check.OutputLength(outBytes, outOff, length, "output buffer too small");
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
return GenerateBytes(outBytes.AsSpan(outOff, length));
|
||||
#else
|
||||
// TODO Create an ASN.1 class for this (RFC3278)
|
||||
// ECC-CMS-SharedInfo
|
||||
DerSequence s = new DerSequence(
|
||||
new AlgorithmIdentifier(algorithm, DerNull.Instance),
|
||||
new DerTaggedObject(true, 2, new DerOctetString(Pack.UInt32_To_BE((uint)keySize))));
|
||||
|
||||
m_kdf.Init(new KdfParameters(z, s.GetDerEncoded()));
|
||||
|
||||
return m_kdf.GenerateBytes(outBytes, outOff, length);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public int GenerateBytes(Span<byte> output)
|
||||
{
|
||||
// TODO Create an ASN.1 class for this (RFC3278)
|
||||
// ECC-CMS-SharedInfo
|
||||
DerSequence s = new DerSequence(
|
||||
new AlgorithmIdentifier(algorithm, DerNull.Instance),
|
||||
new DerTaggedObject(true, 2, new DerOctetString(Pack.UInt32_To_BE((uint)keySize))));
|
||||
|
||||
m_kdf.Init(new KdfParameters(z, s.GetDerEncoded()));
|
||||
|
||||
return m_kdf.GenerateBytes(output);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f8a010d841cddb4448bc3f9784248d3d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/srp.meta
vendored
Normal file
8
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/srp.meta
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3c09d0e66c7efd4b8f36b2bd70fa234
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
168
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/srp/SRP6Client.cs
vendored
Normal file
168
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/srp/SRP6Client.cs
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.Srp
|
||||
{
|
||||
/**
|
||||
* Implements the client side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
|
||||
* This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
|
||||
* "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
|
||||
*/
|
||||
public class Srp6Client
|
||||
{
|
||||
protected BigInteger N;
|
||||
protected BigInteger g;
|
||||
|
||||
protected BigInteger privA;
|
||||
protected BigInteger pubA;
|
||||
|
||||
protected BigInteger B;
|
||||
|
||||
protected BigInteger x;
|
||||
protected BigInteger u;
|
||||
protected BigInteger S;
|
||||
|
||||
protected BigInteger M1;
|
||||
protected BigInteger M2;
|
||||
protected BigInteger Key;
|
||||
|
||||
protected IDigest digest;
|
||||
protected SecureRandom random;
|
||||
|
||||
public Srp6Client()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises the client to begin new authentication attempt
|
||||
* @param N The safe prime associated with the client's verifier
|
||||
* @param g The group parameter associated with the client's verifier
|
||||
* @param digest The digest algorithm associated with the client's verifier
|
||||
* @param random For key generation
|
||||
*/
|
||||
public virtual void Init(BigInteger N, BigInteger g, IDigest digest, SecureRandom random)
|
||||
{
|
||||
this.N = N;
|
||||
this.g = g;
|
||||
this.digest = digest;
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
public virtual void Init(Srp6GroupParameters group, IDigest digest, SecureRandom random)
|
||||
{
|
||||
Init(group.N, group.G, digest, random);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates client's credentials given the client's salt, identity and password
|
||||
* @param salt The salt used in the client's verifier.
|
||||
* @param identity The user's identity (eg. username)
|
||||
* @param password The user's password
|
||||
* @return Client's public value to send to server
|
||||
*/
|
||||
public virtual BigInteger GenerateClientCredentials(byte[] salt, byte[] identity, byte[] password)
|
||||
{
|
||||
this.x = Srp6Utilities.CalculateX(digest, N, salt, identity, password);
|
||||
this.privA = SelectPrivateValue();
|
||||
this.pubA = g.ModPow(privA, N);
|
||||
|
||||
return pubA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates client's verification message given the server's credentials
|
||||
* @param serverB The server's credentials
|
||||
* @return Client's verification message for the server
|
||||
* @throws CryptoException If server's credentials are invalid
|
||||
*/
|
||||
public virtual BigInteger CalculateSecret(BigInteger serverB)
|
||||
{
|
||||
this.B = Srp6Utilities.ValidatePublicValue(N, serverB);
|
||||
this.u = Srp6Utilities.CalculateU(digest, N, pubA, B);
|
||||
this.S = CalculateS();
|
||||
|
||||
return S;
|
||||
}
|
||||
|
||||
protected virtual BigInteger SelectPrivateValue()
|
||||
{
|
||||
return Srp6Utilities.GeneratePrivateValue(digest, N, g, random);
|
||||
}
|
||||
|
||||
private BigInteger CalculateS()
|
||||
{
|
||||
BigInteger k = Srp6Utilities.CalculateK(digest, N, g);
|
||||
BigInteger exp = u.Multiply(x).Add(privA);
|
||||
BigInteger tmp = g.ModPow(x, N).Multiply(k).Mod(N);
|
||||
return B.Subtract(tmp).Mod(N).ModPow(exp, N);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the client evidence message M1 using the previously received values.
|
||||
* To be called after calculating the secret S.
|
||||
* @return M1: the client side generated evidence message
|
||||
* @throws CryptoException
|
||||
*/
|
||||
public virtual BigInteger CalculateClientEvidenceMessage()
|
||||
{
|
||||
// Verify pre-requirements
|
||||
if (this.pubA == null || this.B == null || this.S == null)
|
||||
{
|
||||
throw new CryptoException("Impossible to compute M1: " +
|
||||
"some data are missing from the previous operations (A,B,S)");
|
||||
}
|
||||
// compute the client evidence message 'M1'
|
||||
this.M1 = Srp6Utilities.CalculateM1(digest, N, pubA, B, S);
|
||||
return M1;
|
||||
}
|
||||
|
||||
/** Authenticates the server evidence message M2 received and saves it only if correct.
|
||||
* @param M2: the server side generated evidence message
|
||||
* @return A boolean indicating if the server message M2 was the expected one.
|
||||
* @throws CryptoException
|
||||
*/
|
||||
public virtual bool VerifyServerEvidenceMessage(BigInteger serverM2)
|
||||
{
|
||||
// Verify pre-requirements
|
||||
if (this.pubA == null || this.M1 == null || this.S == null)
|
||||
{
|
||||
throw new CryptoException("Impossible to compute and verify M2: " +
|
||||
"some data are missing from the previous operations (A,M1,S)");
|
||||
}
|
||||
|
||||
// Compute the own server evidence message 'M2'
|
||||
BigInteger computedM2 = Srp6Utilities.CalculateM2(digest, N, pubA, M1, S);
|
||||
if (computedM2.Equals(serverM2))
|
||||
{
|
||||
this.M2 = serverM2;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the final session key as a result of the SRP successful mutual authentication
|
||||
* To be called after verifying the server evidence message M2.
|
||||
* @return Key: the mutually authenticated symmetric session key
|
||||
* @throws CryptoException
|
||||
*/
|
||||
public virtual BigInteger CalculateSessionKey()
|
||||
{
|
||||
// Verify pre-requirements (here we enforce a previous calculation of M1 and M2)
|
||||
if (this.S == null || this.M1 == null || this.M2 == null)
|
||||
{
|
||||
throw new CryptoException("Impossible to compute Key: " +
|
||||
"some data are missing from the previous operations (S,M1,M2)");
|
||||
}
|
||||
this.Key = Srp6Utilities.CalculateKey(digest, N, S);
|
||||
return Key;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4d9d608b0adeb74584b09b8baa01c07
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
167
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/srp/SRP6Server.cs
vendored
Normal file
167
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/srp/SRP6Server.cs
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.Srp
|
||||
{
|
||||
/**
|
||||
* Implements the server side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
|
||||
* This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
|
||||
* "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
|
||||
*/
|
||||
public class Srp6Server
|
||||
{
|
||||
protected BigInteger N;
|
||||
protected BigInteger g;
|
||||
protected BigInteger v;
|
||||
|
||||
protected SecureRandom random;
|
||||
protected IDigest digest;
|
||||
|
||||
protected BigInteger A;
|
||||
|
||||
protected BigInteger privB;
|
||||
protected BigInteger pubB;
|
||||
|
||||
protected BigInteger u;
|
||||
protected BigInteger S;
|
||||
protected BigInteger M1;
|
||||
protected BigInteger M2;
|
||||
protected BigInteger Key;
|
||||
|
||||
public Srp6Server()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises the server to accept a new client authentication attempt
|
||||
* @param N The safe prime associated with the client's verifier
|
||||
* @param g The group parameter associated with the client's verifier
|
||||
* @param v The client's verifier
|
||||
* @param digest The digest algorithm associated with the client's verifier
|
||||
* @param random For key generation
|
||||
*/
|
||||
public virtual void Init(BigInteger N, BigInteger g, BigInteger v, IDigest digest, SecureRandom random)
|
||||
{
|
||||
this.N = N;
|
||||
this.g = g;
|
||||
this.v = v;
|
||||
|
||||
this.random = random;
|
||||
this.digest = digest;
|
||||
}
|
||||
|
||||
public virtual void Init(Srp6GroupParameters group, BigInteger v, IDigest digest, SecureRandom random)
|
||||
{
|
||||
Init(group.N, group.G, v, digest, random);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the server's credentials that are to be sent to the client.
|
||||
* @return The server's public value to the client
|
||||
*/
|
||||
public virtual BigInteger GenerateServerCredentials()
|
||||
{
|
||||
BigInteger k = Srp6Utilities.CalculateK(digest, N, g);
|
||||
this.privB = SelectPrivateValue();
|
||||
this.pubB = k.Multiply(v).Mod(N).Add(g.ModPow(privB, N)).Mod(N);
|
||||
|
||||
return pubB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the client's credentials. If valid the shared secret is generated and returned.
|
||||
* @param clientA The client's credentials
|
||||
* @return A shared secret BigInteger
|
||||
* @throws CryptoException If client's credentials are invalid
|
||||
*/
|
||||
public virtual BigInteger CalculateSecret(BigInteger clientA)
|
||||
{
|
||||
this.A = Srp6Utilities.ValidatePublicValue(N, clientA);
|
||||
this.u = Srp6Utilities.CalculateU(digest, N, A, pubB);
|
||||
this.S = CalculateS();
|
||||
|
||||
return S;
|
||||
}
|
||||
|
||||
protected virtual BigInteger SelectPrivateValue()
|
||||
{
|
||||
return Srp6Utilities.GeneratePrivateValue(digest, N, g, random);
|
||||
}
|
||||
|
||||
private BigInteger CalculateS()
|
||||
{
|
||||
return v.ModPow(u, N).Multiply(A).Mod(N).ModPow(privB, N);
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates the received client evidence message M1 and saves it only if correct.
|
||||
* To be called after calculating the secret S.
|
||||
* @param M1: the client side generated evidence message
|
||||
* @return A boolean indicating if the client message M1 was the expected one.
|
||||
* @throws CryptoException
|
||||
*/
|
||||
public virtual bool VerifyClientEvidenceMessage(BigInteger clientM1)
|
||||
{
|
||||
// Verify pre-requirements
|
||||
if (this.A == null || this.pubB == null || this.S == null)
|
||||
{
|
||||
throw new CryptoException("Impossible to compute and verify M1: " +
|
||||
"some data are missing from the previous operations (A,B,S)");
|
||||
}
|
||||
|
||||
// Compute the own client evidence message 'M1'
|
||||
BigInteger computedM1 = Srp6Utilities.CalculateM1(digest, N, A, pubB, S);
|
||||
if (computedM1.Equals(clientM1))
|
||||
{
|
||||
this.M1 = clientM1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the server evidence message M2 using the previously verified values.
|
||||
* To be called after successfully verifying the client evidence message M1.
|
||||
* @return M2: the server side generated evidence message
|
||||
* @throws CryptoException
|
||||
*/
|
||||
public virtual BigInteger CalculateServerEvidenceMessage()
|
||||
{
|
||||
// Verify pre-requirements
|
||||
if (this.A == null || this.M1 == null || this.S == null)
|
||||
{
|
||||
throw new CryptoException("Impossible to compute M2: " +
|
||||
"some data are missing from the previous operations (A,M1,S)");
|
||||
}
|
||||
|
||||
// Compute the server evidence message 'M2'
|
||||
this.M2 = Srp6Utilities.CalculateM2(digest, N, A, M1, S);
|
||||
return M2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the final session key as a result of the SRP successful mutual authentication
|
||||
* To be called after calculating the server evidence message M2.
|
||||
* @return Key: the mutual authenticated symmetric session key
|
||||
* @throws CryptoException
|
||||
*/
|
||||
public virtual BigInteger CalculateSessionKey()
|
||||
{
|
||||
// Verify pre-requirements
|
||||
if (this.S == null || this.M1 == null || this.M2 == null)
|
||||
{
|
||||
throw new CryptoException("Impossible to compute Key: " +
|
||||
"some data are missing from the previous operations (S,M1,M2)");
|
||||
}
|
||||
this.Key = Srp6Utilities.CalculateKey(digest, N, S);
|
||||
return Key;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d0e886e67aac4f644ad184673e7b20e9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,163 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.Encoders;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.Srp
|
||||
{
|
||||
public class Srp6StandardGroups
|
||||
{
|
||||
private static BigInteger FromHex(string hex)
|
||||
{
|
||||
return new BigInteger(1, Hex.DecodeStrict(hex));
|
||||
}
|
||||
|
||||
private static Srp6GroupParameters FromNG(string hexN, string hexG)
|
||||
{
|
||||
return new Srp6GroupParameters(FromHex(hexN), FromHex(hexG));
|
||||
}
|
||||
|
||||
/*
|
||||
* RFC 5054
|
||||
*/
|
||||
private const string rfc5054_1024_N = "EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C"
|
||||
+ "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4"
|
||||
+ "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29"
|
||||
+ "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A" + "FD5138FE8376435B9FC61D2FC0EB06E3";
|
||||
private const string rfc5054_1024_g = "02";
|
||||
public static readonly Srp6GroupParameters rfc5054_1024 = FromNG(rfc5054_1024_N, rfc5054_1024_g);
|
||||
|
||||
private const string rfc5054_1536_N = "9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA961"
|
||||
+ "4B19CC4D5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F843"
|
||||
+ "80B655BB9A22E8DCDF028A7CEC67F0D08134B1C8B97989149B609E0B"
|
||||
+ "E3BAB63D47548381DBC5B1FC764E3F4B53DD9DA1158BFD3E2B9C8CF5"
|
||||
+ "6EDF019539349627DB2FD53D24B7C48665772E437D6C7F8CE442734A"
|
||||
+ "F7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E5A021FFF5E91479E"
|
||||
+ "8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB";
|
||||
private const string rfc5054_1536_g = "02";
|
||||
public static readonly Srp6GroupParameters rfc5054_1536 = FromNG(rfc5054_1536_N, rfc5054_1536_g);
|
||||
|
||||
private const string rfc5054_2048_N = "AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC319294"
|
||||
+ "3DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310D"
|
||||
+ "CD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FB"
|
||||
+ "D5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF74"
|
||||
+ "7359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A"
|
||||
+ "436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D"
|
||||
+ "5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E73"
|
||||
+ "03CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB6"
|
||||
+ "94B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F" + "9E4AFF73";
|
||||
private const string rfc5054_2048_g = "02";
|
||||
public static readonly Srp6GroupParameters rfc5054_2048 = FromNG(rfc5054_2048_N, rfc5054_2048_g);
|
||||
|
||||
private const string rfc5054_3072_N = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
|
||||
+ "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
|
||||
+ "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
|
||||
+ "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
|
||||
+ "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8"
|
||||
+ "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C"
|
||||
+ "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"
|
||||
+ "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D"
|
||||
+ "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D"
|
||||
+ "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226"
|
||||
+ "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
|
||||
+ "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" + "E0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF";
|
||||
private const string rfc5054_3072_g = "05";
|
||||
public static readonly Srp6GroupParameters rfc5054_3072 = FromNG(rfc5054_3072_N, rfc5054_3072_g);
|
||||
|
||||
private const string rfc5054_4096_N = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
|
||||
+ "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
|
||||
+ "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
|
||||
+ "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
|
||||
+ "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8"
|
||||
+ "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C"
|
||||
+ "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"
|
||||
+ "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D"
|
||||
+ "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D"
|
||||
+ "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226"
|
||||
+ "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
|
||||
+ "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC"
|
||||
+ "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26"
|
||||
+ "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB"
|
||||
+ "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2"
|
||||
+ "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127"
|
||||
+ "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" + "FFFFFFFFFFFFFFFF";
|
||||
private const string rfc5054_4096_g = "05";
|
||||
public static readonly Srp6GroupParameters rfc5054_4096 = FromNG(rfc5054_4096_N, rfc5054_4096_g);
|
||||
|
||||
private const string rfc5054_6144_N = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
|
||||
+ "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
|
||||
+ "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
|
||||
+ "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
|
||||
+ "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8"
|
||||
+ "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C"
|
||||
+ "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"
|
||||
+ "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D"
|
||||
+ "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D"
|
||||
+ "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226"
|
||||
+ "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
|
||||
+ "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC"
|
||||
+ "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26"
|
||||
+ "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB"
|
||||
+ "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2"
|
||||
+ "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127"
|
||||
+ "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
|
||||
+ "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406"
|
||||
+ "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918"
|
||||
+ "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151"
|
||||
+ "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03"
|
||||
+ "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F"
|
||||
+ "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
|
||||
+ "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B"
|
||||
+ "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632"
|
||||
+ "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E" + "6DCC4024FFFFFFFFFFFFFFFF";
|
||||
private const string rfc5054_6144_g = "05";
|
||||
public static readonly Srp6GroupParameters rfc5054_6144 = FromNG(rfc5054_6144_N, rfc5054_6144_g);
|
||||
|
||||
private const string rfc5054_8192_N = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
|
||||
+ "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
|
||||
+ "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
|
||||
+ "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
|
||||
+ "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8"
|
||||
+ "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C"
|
||||
+ "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"
|
||||
+ "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D"
|
||||
+ "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D"
|
||||
+ "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226"
|
||||
+ "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
|
||||
+ "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC"
|
||||
+ "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26"
|
||||
+ "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB"
|
||||
+ "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2"
|
||||
+ "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127"
|
||||
+ "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
|
||||
+ "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406"
|
||||
+ "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918"
|
||||
+ "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151"
|
||||
+ "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03"
|
||||
+ "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F"
|
||||
+ "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
|
||||
+ "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B"
|
||||
+ "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632"
|
||||
+ "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E"
|
||||
+ "6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA"
|
||||
+ "3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C"
|
||||
+ "5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9"
|
||||
+ "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC886"
|
||||
+ "2F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A6"
|
||||
+ "6D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC5"
|
||||
+ "0846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268"
|
||||
+ "359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6"
|
||||
+ "FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" + "60C980DD98EDD3DFFFFFFFFFFFFFFFFF";
|
||||
private const string rfc5054_8192_g = "13";
|
||||
public static readonly Srp6GroupParameters rfc5054_8192 = FromNG(rfc5054_8192_N, rfc5054_8192_g);
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 639f4eb11063b374b9f415ea311f1c26
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
222
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/srp/SRP6Utilities.cs
vendored
Normal file
222
Packages/com.tivadar.best.http/Runtime/3rdParty/BouncyCastle/crypto/agreement/srp/SRP6Utilities.cs
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.Srp
|
||||
{
|
||||
public class Srp6Utilities
|
||||
{
|
||||
public static BigInteger CalculateK(IDigest digest, BigInteger N, BigInteger g)
|
||||
{
|
||||
return HashPaddedPair(digest, N, N, g);
|
||||
}
|
||||
|
||||
public static BigInteger CalculateU(IDigest digest, BigInteger N, BigInteger A, BigInteger B)
|
||||
{
|
||||
return HashPaddedPair(digest, N, A, B);
|
||||
}
|
||||
|
||||
public static BigInteger CalculateX(IDigest digest, BigInteger N, byte[] salt, byte[] identity, byte[] password)
|
||||
{
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
return CalculateX(digest, N, salt.AsSpan(), identity.AsSpan(), password.AsSpan());
|
||||
#else
|
||||
byte[] output = new byte[digest.GetDigestSize()];
|
||||
|
||||
digest.BlockUpdate(identity, 0, identity.Length);
|
||||
digest.Update((byte)':');
|
||||
digest.BlockUpdate(password, 0, password.Length);
|
||||
digest.DoFinal(output, 0);
|
||||
|
||||
digest.BlockUpdate(salt, 0, salt.Length);
|
||||
digest.BlockUpdate(output, 0, output.Length);
|
||||
digest.DoFinal(output, 0);
|
||||
|
||||
return new BigInteger(1, output);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
public static BigInteger CalculateX(IDigest digest, BigInteger N, ReadOnlySpan<byte> salt,
|
||||
ReadOnlySpan<byte> identity, ReadOnlySpan<byte> password)
|
||||
{
|
||||
int digestSize = digest.GetDigestSize();
|
||||
Span<byte> output = digestSize <= 128
|
||||
? stackalloc byte[digestSize]
|
||||
: new byte[digestSize];
|
||||
|
||||
digest.BlockUpdate(identity);
|
||||
digest.Update((byte)':');
|
||||
digest.BlockUpdate(password);
|
||||
digest.DoFinal(output);
|
||||
|
||||
digest.BlockUpdate(salt);
|
||||
digest.BlockUpdate(output);
|
||||
digest.DoFinal(output);
|
||||
|
||||
return new BigInteger(1, output);
|
||||
}
|
||||
#endif
|
||||
|
||||
public static BigInteger GeneratePrivateValue(IDigest digest, BigInteger N, BigInteger g, SecureRandom random)
|
||||
{
|
||||
int minBits = System.Math.Min(256, N.BitLength / 2);
|
||||
BigInteger min = BigInteger.One.ShiftLeft(minBits - 1);
|
||||
BigInteger max = N.Subtract(BigInteger.One);
|
||||
|
||||
return BigIntegers.CreateRandomInRange(min, max, random);
|
||||
}
|
||||
|
||||
public static BigInteger ValidatePublicValue(BigInteger N, BigInteger val)
|
||||
{
|
||||
val = val.Mod(N);
|
||||
|
||||
// Check that val % N != 0
|
||||
if (val.Equals(BigInteger.Zero))
|
||||
throw new CryptoException("Invalid public value: 0");
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the client evidence message (M1) according to the standard routine:
|
||||
* M1 = H( A | B | S )
|
||||
* @param digest The Digest used as the hashing function H
|
||||
* @param N Modulus used to get the pad length
|
||||
* @param A The public client value
|
||||
* @param B The public server value
|
||||
* @param S The secret calculated by both sides
|
||||
* @return M1 The calculated client evidence message
|
||||
*/
|
||||
public static BigInteger CalculateM1(IDigest digest, BigInteger N, BigInteger A, BigInteger B, BigInteger S)
|
||||
{
|
||||
BigInteger M1 = HashPaddedTriplet(digest, N, A, B, S);
|
||||
return M1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the server evidence message (M2) according to the standard routine:
|
||||
* M2 = H( A | M1 | S )
|
||||
* @param digest The Digest used as the hashing function H
|
||||
* @param N Modulus used to get the pad length
|
||||
* @param A The public client value
|
||||
* @param M1 The client evidence message
|
||||
* @param S The secret calculated by both sides
|
||||
* @return M2 The calculated server evidence message
|
||||
*/
|
||||
public static BigInteger CalculateM2(IDigest digest, BigInteger N, BigInteger A, BigInteger M1, BigInteger S)
|
||||
{
|
||||
BigInteger M2 = HashPaddedTriplet(digest, N, A, M1, S);
|
||||
return M2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the final Key according to the standard routine: Key = H(S)
|
||||
* @param digest The Digest used as the hashing function H
|
||||
* @param N Modulus used to get the pad length
|
||||
* @param S The secret calculated by both sides
|
||||
* @return
|
||||
*/
|
||||
public static BigInteger CalculateKey(IDigest digest, BigInteger N, BigInteger S)
|
||||
{
|
||||
int paddedLength = (N.BitLength + 7) / 8;
|
||||
int digestSize = digest.GetDigestSize();
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
Span<byte> bytes = paddedLength <= 512
|
||||
? stackalloc byte[paddedLength]
|
||||
: new byte[paddedLength];
|
||||
BigIntegers.AsUnsignedByteArray(S, bytes);
|
||||
digest.BlockUpdate(bytes);
|
||||
|
||||
Span<byte> output = digestSize <= 128
|
||||
? stackalloc byte[digestSize]
|
||||
: new byte[digestSize];
|
||||
digest.DoFinal(output);
|
||||
#else
|
||||
byte[] bytes = new byte[paddedLength];
|
||||
BigIntegers.AsUnsignedByteArray(S, bytes, 0, bytes.Length);
|
||||
digest.BlockUpdate(bytes, 0, bytes.Length);
|
||||
|
||||
byte[] output = new byte[digestSize];
|
||||
digest.DoFinal(output, 0);
|
||||
#endif
|
||||
|
||||
return new BigInteger(1, output);
|
||||
}
|
||||
|
||||
private static BigInteger HashPaddedTriplet(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2, BigInteger n3)
|
||||
{
|
||||
int paddedLength = (N.BitLength + 7) / 8;
|
||||
int digestSize = digest.GetDigestSize();
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
Span<byte> bytes = paddedLength <= 512
|
||||
? stackalloc byte[paddedLength]
|
||||
: new byte[paddedLength];
|
||||
BigIntegers.AsUnsignedByteArray(n1, bytes);
|
||||
digest.BlockUpdate(bytes);
|
||||
BigIntegers.AsUnsignedByteArray(n2, bytes);
|
||||
digest.BlockUpdate(bytes);
|
||||
BigIntegers.AsUnsignedByteArray(n3, bytes);
|
||||
digest.BlockUpdate(bytes);
|
||||
|
||||
Span<byte> output = digestSize <= 128
|
||||
? stackalloc byte[digestSize]
|
||||
: new byte[digestSize];
|
||||
digest.DoFinal(output);
|
||||
#else
|
||||
byte[] bytes = new byte[paddedLength];
|
||||
BigIntegers.AsUnsignedByteArray(n1, bytes, 0, bytes.Length);
|
||||
digest.BlockUpdate(bytes, 0, bytes.Length);
|
||||
BigIntegers.AsUnsignedByteArray(n2, bytes, 0, bytes.Length);
|
||||
digest.BlockUpdate(bytes, 0, bytes.Length);
|
||||
BigIntegers.AsUnsignedByteArray(n3, bytes, 0, bytes.Length);
|
||||
digest.BlockUpdate(bytes, 0, bytes.Length);
|
||||
|
||||
byte[] output = new byte[digestSize];
|
||||
digest.DoFinal(output, 0);
|
||||
#endif
|
||||
|
||||
return new BigInteger(1, output);
|
||||
}
|
||||
|
||||
private static BigInteger HashPaddedPair(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2)
|
||||
{
|
||||
int paddedLength = (N.BitLength + 7) / 8;
|
||||
int digestSize = digest.GetDigestSize();
|
||||
|
||||
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
|
||||
Span<byte> bytes = paddedLength <= 512
|
||||
? stackalloc byte[paddedLength]
|
||||
: new byte[paddedLength];
|
||||
BigIntegers.AsUnsignedByteArray(n1, bytes);
|
||||
digest.BlockUpdate(bytes);
|
||||
BigIntegers.AsUnsignedByteArray(n2, bytes);
|
||||
digest.BlockUpdate(bytes);
|
||||
|
||||
Span<byte> output = digestSize <= 128
|
||||
? stackalloc byte[digestSize]
|
||||
: new byte[digestSize];
|
||||
digest.DoFinal(output);
|
||||
#else
|
||||
byte[] bytes = new byte[paddedLength];
|
||||
BigIntegers.AsUnsignedByteArray(n1, bytes, 0, bytes.Length);
|
||||
digest.BlockUpdate(bytes, 0, bytes.Length);
|
||||
BigIntegers.AsUnsignedByteArray(n2, bytes, 0, bytes.Length);
|
||||
digest.BlockUpdate(bytes, 0, bytes.Length);
|
||||
|
||||
byte[] output = new byte[digestSize];
|
||||
digest.DoFinal(output, 0);
|
||||
#endif
|
||||
|
||||
return new BigInteger(1, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd559eae0c629b947b49355114a17f2a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,59 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
|
||||
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.Srp
|
||||
{
|
||||
/**
|
||||
* Generates new SRP verifier for user
|
||||
*/
|
||||
public class Srp6VerifierGenerator
|
||||
{
|
||||
protected BigInteger N;
|
||||
protected BigInteger g;
|
||||
protected IDigest digest;
|
||||
|
||||
public Srp6VerifierGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises generator to create new verifiers
|
||||
* @param N The safe prime to use (see DHParametersGenerator)
|
||||
* @param g The group parameter to use (see DHParametersGenerator)
|
||||
* @param digest The digest to use. The same digest type will need to be used later for the actual authentication
|
||||
* attempt. Also note that the final session key size is dependent on the chosen digest.
|
||||
*/
|
||||
public virtual void Init(BigInteger N, BigInteger g, IDigest digest)
|
||||
{
|
||||
this.N = N;
|
||||
this.g = g;
|
||||
this.digest = digest;
|
||||
}
|
||||
|
||||
public virtual void Init(Srp6GroupParameters group, IDigest digest)
|
||||
{
|
||||
Init(group.N, group.G, digest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new SRP verifier
|
||||
* @param salt The salt to use, generally should be large and random
|
||||
* @param identity The user's identifying information (eg. username)
|
||||
* @param password The user's password
|
||||
* @return A new verifier for use in future SRP authentication
|
||||
*/
|
||||
public virtual BigInteger GenerateVerifier(byte[] salt, byte[] identity, byte[] password)
|
||||
{
|
||||
BigInteger x = Srp6Utilities.CalculateX(digest, N, salt, identity, password);
|
||||
|
||||
return g.ModPow(x, N);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd68ce3a83ec3c946bf48a047e69fea0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user